diff options
Diffstat (limited to 'ipc/chromium/src/mojo/core/ports/event.cc')
-rw-r--r-- | ipc/chromium/src/mojo/core/ports/event.cc | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/ipc/chromium/src/mojo/core/ports/event.cc b/ipc/chromium/src/mojo/core/ports/event.cc new file mode 100644 index 0000000000..32e0bbbaa8 --- /dev/null +++ b/ipc/chromium/src/mojo/core/ports/event.cc @@ -0,0 +1,471 @@ +// 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 "mojo/core/ports/user_message.h" +#include "mozilla/Assertions.h" +#include "mozilla/CheckedInt.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; +}; + +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; +}; + +#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."); + +} // 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; + const size_t data_size = num_bytes - sizeof(*header); + switch (header->type) { + case Type::kUserMessage: + return UserMessageEvent::Deserialize(port_name, header + 1, data_size); + case Type::kPortAccepted: + return PortAcceptedEvent::Deserialize(port_name, header + 1, data_size); + case Type::kObserveProxy: + return ObserveProxyEvent::Deserialize(port_name, header + 1, data_size); + case Type::kObserveProxyAck: + return ObserveProxyAckEvent::Deserialize(port_name, header + 1, + data_size); + case Type::kObserveClosure: + return ObserveClosureEvent::Deserialize(port_name, header + 1, data_size); + case Type::kMergePort: + return MergePortEvent::Deserialize(port_name, header + 1, data_size); + case Type::kUserMessageReadAckRequest: + return UserMessageReadAckRequestEvent::Deserialize(port_name, header + 1, + data_size); + case Type::kUserMessageReadAck: + return UserMessageReadAckEvent::Deserialize(port_name, 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) + : type_(type), port_name_(port_name) {} + +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_; + SerializeData(header + 1); +} + +ScopedEvent Event::Clone() const { return nullptr; } + +UserMessageEvent::~UserMessageEvent() = default; + +UserMessageEvent::UserMessageEvent(size_t num_ports) + : Event(Type::kUserMessage, kInvalidPortName) { + ReservePorts(num_ports); +} + +void UserMessageEvent::AttachMessage(mozilla::UniquePtr<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(*this); +} + +// static +ScopedEvent UserMessageEvent::Deserialize(const PortName& port_name, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(UserMessageEventData)) { + return nullptr; + } + + const auto* data = static_cast<const UserMessageEventData*>(buffer); + mozilla::CheckedInt<size_t> port_data_size = data->num_ports; + port_data_size *= sizeof(PortDescriptor) + sizeof(PortName); + if (!port_data_size.isValid()) { + return nullptr; + } + + mozilla::CheckedInt<size_t> total_size = port_data_size.value(); + total_size += sizeof(UserMessageEventData); + if (!total_size.isValid() || num_bytes < total_size.value()) { + return nullptr; + } + + auto event = + mozilla::WrapUnique(new UserMessageEvent(port_name, 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 event; +} + +UserMessageEvent::UserMessageEvent(const PortName& port_name, + uint64_t sequence_num) + : Event(Type::kUserMessage, port_name), 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()); + mozilla::CheckedInt<size_t> size = sizeof(UserMessageEventData); + mozilla::CheckedInt<size_t> ports_size = + sizeof(PortDescriptor) + sizeof(PortName); + ports_size *= ports_.size(); + mozilla::CheckedInt<size_t> combined = size + ports_size; + MOZ_RELEASE_ASSERT(combined.isValid()); + return combined.value(); +} + +void UserMessageEvent::SerializeData(void* buffer) const { + DCHECK_EQ(ports_.size(), port_descriptors_.size()); + auto* data = static_cast<UserMessageEventData*>(buffer); + data->sequence_num = sequence_num_; + mozilla::CheckedInt<uint32_t> num_ports{ports_.size()}; + DCHECK(num_ports.isValid()); + data->num_ports = num_ports.value(); + 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) + : Event(Type::kPortAccepted, port_name) {} + +PortAcceptedEvent::~PortAcceptedEvent() = default; + +// static +ScopedEvent PortAcceptedEvent::Deserialize(const PortName& port_name, + const void* buffer, + size_t num_bytes) { + return mozilla::MakeUnique<PortAcceptedEvent>(port_name); +} + +size_t PortAcceptedEvent::GetSerializedDataSize() const { return 0; } + +void PortAcceptedEvent::SerializeData(void* buffer) const {} + +ObserveProxyEvent::ObserveProxyEvent(const PortName& port_name, + 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), + 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 void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(ObserveProxyEventData)) { + return nullptr; + } + + const auto* data = static_cast<const ObserveProxyEventData*>(buffer); + return mozilla::MakeUnique<ObserveProxyEvent>( + port_name, 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::Clone() const { + return mozilla::MakeUnique<ObserveProxyEvent>( + port_name(), proxy_node_name_, proxy_port_name_, proxy_target_node_name_, + proxy_target_port_name_); +} + +ObserveProxyAckEvent::ObserveProxyAckEvent(const PortName& port_name, + uint64_t last_sequence_num) + : Event(Type::kObserveProxyAck, port_name), + last_sequence_num_(last_sequence_num) {} + +ObserveProxyAckEvent::~ObserveProxyAckEvent() = default; + +// static +ScopedEvent ObserveProxyAckEvent::Deserialize(const PortName& port_name, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(ObserveProxyAckEventData)) { + return nullptr; + } + + const auto* data = static_cast<const ObserveProxyAckEventData*>(buffer); + return mozilla::MakeUnique<ObserveProxyAckEvent>(port_name, + 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_; +} + +ScopedEvent ObserveProxyAckEvent::Clone() const { + return mozilla::MakeUnique<ObserveProxyAckEvent>(port_name(), + last_sequence_num_); +} + +ObserveClosureEvent::ObserveClosureEvent(const PortName& port_name, + uint64_t last_sequence_num) + : Event(Type::kObserveClosure, port_name), + last_sequence_num_(last_sequence_num) {} + +ObserveClosureEvent::~ObserveClosureEvent() = default; + +// static +ScopedEvent ObserveClosureEvent::Deserialize(const PortName& port_name, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(ObserveClosureEventData)) { + return nullptr; + } + + const auto* data = static_cast<const ObserveClosureEventData*>(buffer); + return mozilla::MakeUnique<ObserveClosureEvent>(port_name, + 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_; +} + +ScopedEvent ObserveClosureEvent::Clone() const { + return mozilla::MakeUnique<ObserveClosureEvent>(port_name(), + last_sequence_num_); +} + +MergePortEvent::MergePortEvent(const PortName& port_name, + const PortName& new_port_name, + const PortDescriptor& new_port_descriptor) + : Event(Type::kMergePort, port_name), + new_port_name_(new_port_name), + new_port_descriptor_(new_port_descriptor) {} + +MergePortEvent::~MergePortEvent() = default; + +// static +ScopedEvent MergePortEvent::Deserialize(const PortName& port_name, + const void* buffer, size_t num_bytes) { + if (num_bytes < sizeof(MergePortEventData)) { + return nullptr; + } + + const auto* data = static_cast<const MergePortEventData*>(buffer); + return mozilla::MakeUnique<MergePortEvent>(port_name, 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, uint64_t sequence_num_to_acknowledge) + : Event(Type::kUserMessageReadAckRequest, port_name), + sequence_num_to_acknowledge_(sequence_num_to_acknowledge) {} + +UserMessageReadAckRequestEvent::~UserMessageReadAckRequestEvent() = default; + +// static +ScopedEvent UserMessageReadAckRequestEvent::Deserialize( + const PortName& port_name, const void* buffer, size_t num_bytes) { + if (num_bytes < sizeof(UserMessageReadAckRequestEventData)) { + return nullptr; + } + + const auto* data = + static_cast<const UserMessageReadAckRequestEventData*>(buffer); + return mozilla::MakeUnique<UserMessageReadAckRequestEvent>( + port_name, 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, uint64_t sequence_num_acknowledged) + : Event(Type::kUserMessageReadAck, port_name), + sequence_num_acknowledged_(sequence_num_acknowledged) {} + +UserMessageReadAckEvent::~UserMessageReadAckEvent() = default; + +// static +ScopedEvent UserMessageReadAckEvent::Deserialize(const PortName& port_name, + const void* buffer, + size_t num_bytes) { + if (num_bytes < sizeof(UserMessageReadAckEventData)) { + return nullptr; + } + + const auto* data = static_cast<const UserMessageReadAckEventData*>(buffer); + return mozilla::MakeUnique<UserMessageReadAckEvent>( + port_name, 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_; +} + +} // namespace ports +} // namespace core +} // namespace mojo |