| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "mojo/core/ports/event.h" |
| |
| #include <stdint.h> |
| #include <string.h> |
| |
| #include "base/logging.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/numerics/safe_math.h" |
| #include "mojo/core/ports/user_message.h" |
| |
| namespace mojo { |
| namespace core { |
| namespace ports { |
| |
| namespace { |
| |
| const size_t kPortsMessageAlignment = 8; |
| |
| #pragma pack(push, 1) |
| |
| struct SerializedHeader { |
| Event::Type type; |
| uint32_t padding; |
| PortName port_name; |
| #ifndef MOJO_BACKWARDS_COMPAT |
| PortName from_port; |
| uint64_t control_sequence_num; |
| #endif |
| }; |
| |
| struct UserMessageEventData { |
| uint64_t sequence_num; |
| uint32_t num_ports; |
| uint32_t padding; |
| }; |
| |
| struct ObserveProxyEventData { |
| NodeName proxy_node_name; |
| PortName proxy_port_name; |
| NodeName proxy_target_node_name; |
| PortName proxy_target_port_name; |
| }; |
| |
| struct ObserveProxyAckEventData { |
| uint64_t last_sequence_num; |
| }; |
| |
| struct ObserveClosureEventData { |
| uint64_t last_sequence_num; |
| }; |
| |
| struct MergePortEventData { |
| PortName new_port_name; |
| Event::PortDescriptor new_port_descriptor; |
| }; |
| |
| struct UserMessageReadAckRequestEventData { |
| uint64_t sequence_num_to_acknowledge; |
| }; |
| |
| struct UserMessageReadAckEventData { |
| uint64_t sequence_num_acknowledged; |
| }; |
| |
| struct UpdatePreviousPeerEventData { |
| NodeName new_node_name; |
| PortName new_port_name; |
| }; |
| |
| #pragma pack(pop) |
| |
| static_assert(sizeof(Event::PortDescriptor) % kPortsMessageAlignment == 0, |
| "Invalid PortDescriptor size."); |
| |
| static_assert(sizeof(SerializedHeader) % kPortsMessageAlignment == 0, |
| "Invalid SerializedHeader size."); |
| |
| static_assert(sizeof(UserMessageEventData) % kPortsMessageAlignment == 0, |
| "Invalid UserEventData size."); |
| |
| static_assert(sizeof(ObserveProxyEventData) % kPortsMessageAlignment == 0, |
| "Invalid ObserveProxyEventData size."); |
| |
| static_assert(sizeof(ObserveProxyAckEventData) % kPortsMessageAlignment == 0, |
| "Invalid ObserveProxyAckEventData size."); |
| |
| static_assert(sizeof(ObserveClosureEventData) % kPortsMessageAlignment == 0, |
| "Invalid ObserveClosureEventData size."); |
| |
| static_assert(sizeof(MergePortEventData) % kPortsMessageAlignment == 0, |
| "Invalid MergePortEventData size."); |
| |
| static_assert(sizeof(UserMessageReadAckRequestEventData) % |
| kPortsMessageAlignment == |
| 0, |
| "Invalid UserMessageReadAckRequestEventData size."); |
| |
| static_assert(sizeof(UserMessageReadAckEventData) % kPortsMessageAlignment == 0, |
| "Invalid UserMessageReadAckEventData size."); |
| |
| static_assert(sizeof(UpdatePreviousPeerEventData) % kPortsMessageAlignment == 0, |
| "Invalid UpdatePreviousPeerEventData size."); |
| |
| } // namespace |
| |
| Event::PortDescriptor::PortDescriptor() { |
| memset(padding, 0, sizeof(padding)); |
| } |
| |
| Event::~Event() = default; |
| |
| // static |
| ScopedEvent Event::Deserialize(const void* buffer, size_t num_bytes) { |
| if (num_bytes < sizeof(SerializedHeader)) |
| return nullptr; |
| |
| const auto* header = static_cast<const SerializedHeader*>(buffer); |
| const PortName& port_name = header->port_name; |
| #ifndef MOJO_BACKWARDS_COMPAT |
| const PortName& from_port = header->from_port; |
| const uint64_t control_sequence_num = header->control_sequence_num; |
| #else |
| const PortName& from_port = kInvalidPortName; |
| const uint64_t control_sequence_num = std::numeric_limits<uint64_t>::max(); |
| #endif |
| const size_t data_size = num_bytes - sizeof(*header); |
| switch (header->type) { |
| case Type::kUserMessage: |
| return UserMessageEvent::Deserialize( |
| port_name, from_port, control_sequence_num, header + 1, data_size); |
| case Type::kPortAccepted: |
| return PortAcceptedEvent::Deserialize( |
| port_name, from_port, control_sequence_num, header + 1, data_size); |
| case Type::kObserveProxy: |
| return ObserveProxyEvent::Deserialize( |
| port_name, from_port, control_sequence_num, header + 1, data_size); |
| case Type::kObserveProxyAck: |
| return ObserveProxyAckEvent::Deserialize( |
| port_name, from_port, control_sequence_num, header + 1, data_size); |
| case Type::kObserveClosure: |
| return ObserveClosureEvent::Deserialize( |
| port_name, from_port, control_sequence_num, header + 1, data_size); |
| case Type::kMergePort: |
| return MergePortEvent::Deserialize( |
| port_name, from_port, control_sequence_num, header + 1, data_size); |
| case Type::kUserMessageReadAckRequest: |
| return UserMessageReadAckRequestEvent::Deserialize( |
| port_name, from_port, control_sequence_num, header + 1, data_size); |
| case Type::kUserMessageReadAck: |
| return UserMessageReadAckEvent::Deserialize( |
| port_name, from_port, control_sequence_num, header + 1, data_size); |
| case Type::kUpdatePreviousPeer: |
| return UpdatePreviousPeerEvent::Deserialize( |
| port_name, from_port, control_sequence_num, header + 1, data_size); |
| default: |
| DVLOG(2) << "Ingoring unknown port event type: " |
| << static_cast<uint32_t>(header->type); |
| return nullptr; |
| } |
| } |
| |
| Event::Event(Type type, |
| const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num) |
| : type_(type), |
| port_name_(port_name), |
| from_port_(from_port), |
| control_sequence_num_(control_sequence_num) {} |
| |
| size_t Event::GetSerializedSize() const { |
| return sizeof(SerializedHeader) + GetSerializedDataSize(); |
| } |
| |
| void Event::Serialize(void* buffer) const { |
| auto* header = static_cast<SerializedHeader*>(buffer); |
| header->type = type_; |
| header->padding = 0; |
| header->port_name = port_name_; |
| #ifndef MOJO_BACKWARDS_COMPAT |
| header->from_port = from_port_; |
| header->control_sequence_num = control_sequence_num_; |
| #endif |
| SerializeData(header + 1); |
| } |
| |
| ScopedEvent Event::CloneForBroadcast() const { |
| return nullptr; |
| } |
| |
| UserMessageEvent::~UserMessageEvent() = default; |
| |
| UserMessageEvent::UserMessageEvent(size_t num_ports) |
| : Event(Type::kUserMessage, kInvalidPortName, kInvalidPortName, -1) { |
| ReservePorts(num_ports); |
| } |
| |
| void UserMessageEvent::AttachMessage(std::unique_ptr<UserMessage> message) { |
| DCHECK(!message_); |
| message_ = std::move(message); |
| } |
| |
| void UserMessageEvent::ReservePorts(size_t num_ports) { |
| port_descriptors_.resize(num_ports); |
| ports_.resize(num_ports); |
| } |
| |
| bool UserMessageEvent::NotifyWillBeRoutedExternally() { |
| DCHECK(message_); |
| return message_->WillBeRoutedExternally(); |
| } |
| |
| // static |
| ScopedEvent UserMessageEvent::Deserialize(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const void* buffer, |
| size_t num_bytes) { |
| if (num_bytes < sizeof(UserMessageEventData)) |
| return nullptr; |
| |
| const auto* data = static_cast<const UserMessageEventData*>(buffer); |
| base::CheckedNumeric<size_t> port_data_size = data->num_ports; |
| port_data_size *= sizeof(PortDescriptor) + sizeof(PortName); |
| if (!port_data_size.IsValid()) |
| return nullptr; |
| |
| base::CheckedNumeric<size_t> total_size = port_data_size.ValueOrDie(); |
| total_size += sizeof(UserMessageEventData); |
| if (!total_size.IsValid() || num_bytes < total_size.ValueOrDie()) |
| return nullptr; |
| |
| auto event = base::WrapUnique(new UserMessageEvent( |
| port_name, from_port, control_sequence_num, data->sequence_num)); |
| event->ReservePorts(data->num_ports); |
| const auto* in_descriptors = |
| reinterpret_cast<const PortDescriptor*>(data + 1); |
| std::copy(in_descriptors, in_descriptors + data->num_ports, |
| event->port_descriptors()); |
| |
| const auto* in_names = |
| reinterpret_cast<const PortName*>(in_descriptors + data->num_ports); |
| std::copy(in_names, in_names + data->num_ports, event->ports()); |
| return std::move(event); |
| } |
| |
| UserMessageEvent::UserMessageEvent(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| uint64_t sequence_num) |
| : Event(Type::kUserMessage, port_name, from_port, control_sequence_num), |
| sequence_num_(sequence_num) {} |
| |
| size_t UserMessageEvent::GetSizeIfSerialized() const { |
| if (!message_) |
| return 0; |
| return message_->GetSizeIfSerialized(); |
| } |
| |
| size_t UserMessageEvent::GetSerializedDataSize() const { |
| DCHECK_EQ(ports_.size(), port_descriptors_.size()); |
| base::CheckedNumeric<size_t> size = sizeof(UserMessageEventData); |
| base::CheckedNumeric<size_t> ports_size = |
| sizeof(PortDescriptor) + sizeof(PortName); |
| ports_size *= ports_.size(); |
| return (size + ports_size.ValueOrDie()).ValueOrDie(); |
| } |
| |
| void UserMessageEvent::SerializeData(void* buffer) const { |
| DCHECK_EQ(ports_.size(), port_descriptors_.size()); |
| auto* data = static_cast<UserMessageEventData*>(buffer); |
| data->sequence_num = sequence_num_; |
| DCHECK(base::IsValueInRangeForNumericType<uint32_t>(ports_.size())); |
| data->num_ports = static_cast<uint32_t>(ports_.size()); |
| data->padding = 0; |
| |
| auto* ports_data = reinterpret_cast<PortDescriptor*>(data + 1); |
| std::copy(port_descriptors_.begin(), port_descriptors_.end(), ports_data); |
| |
| auto* port_names_data = |
| reinterpret_cast<PortName*>(ports_data + ports_.size()); |
| std::copy(ports_.begin(), ports_.end(), port_names_data); |
| } |
| |
| PortAcceptedEvent::PortAcceptedEvent(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num) |
| : Event(Type::kPortAccepted, port_name, from_port, control_sequence_num) {} |
| |
| PortAcceptedEvent::~PortAcceptedEvent() = default; |
| |
| // static |
| ScopedEvent PortAcceptedEvent::Deserialize(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const void* buffer, |
| size_t num_bytes) { |
| return std::make_unique<PortAcceptedEvent>(port_name, from_port, |
| control_sequence_num); |
| } |
| |
| size_t PortAcceptedEvent::GetSerializedDataSize() const { |
| return 0; |
| } |
| |
| void PortAcceptedEvent::SerializeData(void* buffer) const {} |
| |
| ObserveProxyEvent::ObserveProxyEvent(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const NodeName& proxy_node_name, |
| const PortName& proxy_port_name, |
| const NodeName& proxy_target_node_name, |
| const PortName& proxy_target_port_name) |
| : Event(Type::kObserveProxy, port_name, from_port, control_sequence_num), |
| proxy_node_name_(proxy_node_name), |
| proxy_port_name_(proxy_port_name), |
| proxy_target_node_name_(proxy_target_node_name), |
| proxy_target_port_name_(proxy_target_port_name) {} |
| |
| ObserveProxyEvent::~ObserveProxyEvent() = default; |
| |
| // static |
| ScopedEvent ObserveProxyEvent::Deserialize(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const void* buffer, |
| size_t num_bytes) { |
| if (num_bytes < sizeof(ObserveProxyEventData)) |
| return nullptr; |
| |
| const auto* data = static_cast<const ObserveProxyEventData*>(buffer); |
| return std::make_unique<ObserveProxyEvent>( |
| port_name, from_port, control_sequence_num, data->proxy_node_name, |
| data->proxy_port_name, data->proxy_target_node_name, |
| data->proxy_target_port_name); |
| } |
| |
| size_t ObserveProxyEvent::GetSerializedDataSize() const { |
| return sizeof(ObserveProxyEventData); |
| } |
| |
| void ObserveProxyEvent::SerializeData(void* buffer) const { |
| auto* data = static_cast<ObserveProxyEventData*>(buffer); |
| data->proxy_node_name = proxy_node_name_; |
| data->proxy_port_name = proxy_port_name_; |
| data->proxy_target_node_name = proxy_target_node_name_; |
| data->proxy_target_port_name = proxy_target_port_name_; |
| } |
| |
| ScopedEvent ObserveProxyEvent::CloneForBroadcast() const { |
| // Don't broadcast events targeted at specific ports. Otherwise a malicioius |
| // node can use this to bypass sender verification. |
| if (port_name() != kInvalidPortName) { |
| return nullptr; |
| } |
| return std::make_unique<ObserveProxyEvent>( |
| port_name(), from_port(), control_sequence_num(), proxy_node_name_, |
| proxy_port_name_, proxy_target_node_name_, proxy_target_port_name_); |
| } |
| |
| ObserveProxyAckEvent::ObserveProxyAckEvent(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| uint64_t last_sequence_num) |
| : Event(Type::kObserveProxyAck, port_name, from_port, control_sequence_num), |
| last_sequence_num_(last_sequence_num) {} |
| |
| ObserveProxyAckEvent::~ObserveProxyAckEvent() = default; |
| |
| // static |
| ScopedEvent ObserveProxyAckEvent::Deserialize(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const void* buffer, |
| size_t num_bytes) { |
| if (num_bytes < sizeof(ObserveProxyAckEventData)) |
| return nullptr; |
| |
| const auto* data = static_cast<const ObserveProxyAckEventData*>(buffer); |
| return std::make_unique<ObserveProxyAckEvent>( |
| port_name, from_port, control_sequence_num, data->last_sequence_num); |
| } |
| |
| size_t ObserveProxyAckEvent::GetSerializedDataSize() const { |
| return sizeof(ObserveProxyAckEventData); |
| } |
| |
| void ObserveProxyAckEvent::SerializeData(void* buffer) const { |
| auto* data = static_cast<ObserveProxyAckEventData*>(buffer); |
| data->last_sequence_num = last_sequence_num_; |
| } |
| |
| ObserveClosureEvent::ObserveClosureEvent(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| uint64_t last_sequence_num) |
| : Event(Type::kObserveClosure, port_name, from_port, control_sequence_num), |
| last_sequence_num_(last_sequence_num) {} |
| |
| ObserveClosureEvent::~ObserveClosureEvent() = default; |
| |
| // static |
| ScopedEvent ObserveClosureEvent::Deserialize(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const void* buffer, |
| size_t num_bytes) { |
| if (num_bytes < sizeof(ObserveClosureEventData)) |
| return nullptr; |
| |
| const auto* data = static_cast<const ObserveClosureEventData*>(buffer); |
| return std::make_unique<ObserveClosureEvent>( |
| port_name, from_port, control_sequence_num, data->last_sequence_num); |
| } |
| |
| size_t ObserveClosureEvent::GetSerializedDataSize() const { |
| return sizeof(ObserveClosureEventData); |
| } |
| |
| void ObserveClosureEvent::SerializeData(void* buffer) const { |
| auto* data = static_cast<ObserveClosureEventData*>(buffer); |
| data->last_sequence_num = last_sequence_num_; |
| } |
| |
| MergePortEvent::MergePortEvent(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const PortName& new_port_name, |
| const PortDescriptor& new_port_descriptor) |
| : Event(Type::kMergePort, port_name, from_port, control_sequence_num), |
| new_port_name_(new_port_name), |
| new_port_descriptor_(new_port_descriptor) {} |
| |
| MergePortEvent::~MergePortEvent() = default; |
| |
| // static |
| ScopedEvent MergePortEvent::Deserialize(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const void* buffer, |
| size_t num_bytes) { |
| if (num_bytes < sizeof(MergePortEventData)) |
| return nullptr; |
| |
| const auto* data = static_cast<const MergePortEventData*>(buffer); |
| return std::make_unique<MergePortEvent>( |
| port_name, from_port, control_sequence_num, data->new_port_name, |
| data->new_port_descriptor); |
| } |
| |
| size_t MergePortEvent::GetSerializedDataSize() const { |
| return sizeof(MergePortEventData); |
| } |
| |
| void MergePortEvent::SerializeData(void* buffer) const { |
| auto* data = static_cast<MergePortEventData*>(buffer); |
| data->new_port_name = new_port_name_; |
| data->new_port_descriptor = new_port_descriptor_; |
| } |
| |
| UserMessageReadAckRequestEvent::UserMessageReadAckRequestEvent( |
| const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| uint64_t sequence_num_to_acknowledge) |
| : Event(Type::kUserMessageReadAckRequest, |
| port_name, |
| from_port, |
| control_sequence_num), |
| sequence_num_to_acknowledge_(sequence_num_to_acknowledge) {} |
| |
| UserMessageReadAckRequestEvent::~UserMessageReadAckRequestEvent() = default; |
| |
| // static |
| ScopedEvent UserMessageReadAckRequestEvent::Deserialize( |
| const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const void* buffer, |
| size_t num_bytes) { |
| if (num_bytes < sizeof(UserMessageReadAckRequestEventData)) |
| return nullptr; |
| |
| const auto* data = |
| static_cast<const UserMessageReadAckRequestEventData*>(buffer); |
| return std::make_unique<UserMessageReadAckRequestEvent>( |
| port_name, from_port, control_sequence_num, |
| data->sequence_num_to_acknowledge); |
| } |
| |
| size_t UserMessageReadAckRequestEvent::GetSerializedDataSize() const { |
| return sizeof(UserMessageReadAckRequestEventData); |
| } |
| |
| void UserMessageReadAckRequestEvent::SerializeData(void* buffer) const { |
| auto* data = static_cast<UserMessageReadAckRequestEventData*>(buffer); |
| data->sequence_num_to_acknowledge = sequence_num_to_acknowledge_; |
| } |
| |
| UserMessageReadAckEvent::UserMessageReadAckEvent( |
| const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| uint64_t sequence_num_acknowledged) |
| : Event(Type::kUserMessageReadAck, |
| port_name, |
| from_port, |
| control_sequence_num), |
| sequence_num_acknowledged_(sequence_num_acknowledged) {} |
| |
| UserMessageReadAckEvent::~UserMessageReadAckEvent() = default; |
| |
| // static |
| ScopedEvent UserMessageReadAckEvent::Deserialize(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const void* buffer, |
| size_t num_bytes) { |
| if (num_bytes < sizeof(UserMessageReadAckEventData)) |
| return nullptr; |
| |
| const auto* data = static_cast<const UserMessageReadAckEventData*>(buffer); |
| return std::make_unique<UserMessageReadAckEvent>( |
| port_name, from_port, control_sequence_num, |
| data->sequence_num_acknowledged); |
| } |
| |
| size_t UserMessageReadAckEvent::GetSerializedDataSize() const { |
| return sizeof(UserMessageReadAckEventData); |
| } |
| |
| void UserMessageReadAckEvent::SerializeData(void* buffer) const { |
| auto* data = static_cast<UserMessageReadAckEventData*>(buffer); |
| data->sequence_num_acknowledged = sequence_num_acknowledged_; |
| } |
| |
| UpdatePreviousPeerEvent::UpdatePreviousPeerEvent(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const NodeName& new_node_name, |
| const PortName& new_port_name) |
| : Event(Type::kUpdatePreviousPeer, |
| port_name, |
| from_port, |
| control_sequence_num), |
| new_node_name_(new_node_name), |
| new_port_name_(new_port_name) {} |
| |
| UpdatePreviousPeerEvent::~UpdatePreviousPeerEvent() = default; |
| |
| // static |
| ScopedEvent UpdatePreviousPeerEvent::Deserialize(const PortName& port_name, |
| const PortName& from_port, |
| uint64_t control_sequence_num, |
| const void* buffer, |
| size_t num_bytes) { |
| if (num_bytes < sizeof(UpdatePreviousPeerEventData)) |
| return nullptr; |
| |
| const auto* data = static_cast<const UpdatePreviousPeerEventData*>(buffer); |
| return std::make_unique<UpdatePreviousPeerEvent>( |
| port_name, from_port, control_sequence_num, data->new_node_name, |
| data->new_port_name); |
| } |
| |
| size_t UpdatePreviousPeerEvent::GetSerializedDataSize() const { |
| return sizeof(UpdatePreviousPeerEventData); |
| } |
| |
| void UpdatePreviousPeerEvent::SerializeData(void* buffer) const { |
| auto* data = static_cast<UpdatePreviousPeerEventData*>(buffer); |
| data->new_node_name = new_node_name_; |
| data->new_port_name = new_port_name_; |
| } |
| |
| } // namespace ports |
| } // namespace core |
| } // namespace mojo |