| {{/* |
| // Copyright 2021 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| */}} |
| |
| {{- define "Protocol:EventHandler:WireMessagingHeader" }} |
| {{- EnsureNamespace "" }} |
| {{- IfdefFuchsia }} |
| template<> |
| class {{ .WireEventHandlerInterface }} { |
| public: |
| {{ .WireEventHandlerInterface.Self }}() = default; |
| virtual ~{{ .WireEventHandlerInterface.Self }}() = default; |
| {{- range .Events -}} |
| {{- .Docs }} |
| virtual void {{ .Name }}({{ .WireEvent }}* event) = 0; |
| {{- end }} |
| }; |
| |
| template<> |
| class {{ .WireAsyncEventHandler }} |
| : public {{ .WireEventHandlerInterface }}, public ::fidl::internal::AsyncEventHandler { |
| public: |
| {{ .WireAsyncEventHandler.Self }}() = default; |
| {{- range .Events -}} |
| {{- .Docs }} |
| void {{ .Name }}({{ .WireEvent }}* event) override {} |
| {{- end }} |
| }; |
| |
| template<> |
| class {{ .WireSyncEventHandler }} : public {{ .WireEventHandlerInterface }} { |
| public: |
| {{ .WireSyncEventHandler.Self }}() = default; |
| |
| {{- range .Events }} |
| {{- if .Transitional }} |
| void {{ .Name }}({{ .WireEvent }}* event) override { got_transitional_ = true; } |
| {{- end }} |
| {{- end }} |
| |
| // Handle all possible events defined in this protocol. |
| // Blocks to consume exactly one message from the channel, then call the corresponding virtual |
| // method. |
| ::fidl::Status HandleOneEvent( |
| ::{{ .Transport.Namespace }}::UnownedClientEnd<{{ . }}> client_end); |
| |
| private: |
| [[maybe_unused]] |
| bool got_transitional_ = false; |
| }; |
| |
| template <> |
| class {{ .WireEventDispatcher }} final : |
| public ::fidl::internal::IncomingEventDispatcher<{{ .WireAsyncEventHandler }}> { |
| public: |
| explicit {{ .WireEventDispatcher.Self }}({{ .WireAsyncEventHandler }}* event_handler) |
| : IncomingEventDispatcher(event_handler) {} |
| |
| private: |
| std::optional<::fidl::UnbindInfo> DispatchEvent( |
| ::fidl::IncomingMessage& msg, |
| ::fidl::internal::IncomingTransportContext transport_context) override; |
| }; |
| {{- EndifFuchsia }} |
| {{- end }} |
| |
| |
| |
| {{- define "Protocol:EventHandler:WireMessagingSource" }} |
| {{ EnsureNamespace "" }} |
| {{- IfdefFuchsia }} |
| {{ if .Transport.HasEvents }} |
| ::fidl::Status {{ .WireSyncEventHandler.NoLeading }}::HandleOneEvent( |
| ::{{ .Transport.Namespace }}::UnownedClientEnd<{{ . }}> client_end) { |
| zx_status_t status = client_end.channel()->wait_one(ZX_CHANNEL_READABLE | ZX_CHANNEL_PEER_CLOSED, |
| ::zx::time::infinite(), |
| nullptr); |
| if (status != ZX_OK) { |
| return ::fidl::Status::TransportError(status, ::fidl::internal::kErrorWaitOneFailed); |
| } |
| constexpr uint32_t kHandleAllocSize = ([]() constexpr { |
| uint32_t x = 0; |
| {{- range .Events }} |
| if (::fidl::TypeTraits<{{ .WireTransactionalEvent }}>::kMaxNumHandles >= x) { |
| x = ::fidl::TypeTraits<{{ .WireTransactionalEvent }}>::kMaxNumHandles; |
| } |
| {{- end }} |
| if (x > ZX_CHANNEL_MAX_MSG_HANDLES) { |
| x = ZX_CHANNEL_MAX_MSG_HANDLES; |
| } |
| return x; |
| })(); |
| static_assert(kHandleAllocSize <= ZX_CHANNEL_MAX_MSG_HANDLES); |
| {{ .SyncEventAllocationV1.BackingBufferType }} read_storage; |
| std::array<zx_handle_t, kHandleAllocSize> read_handles; |
| // TODO(fxbug.dev/85734) Remove this channel-specific allocation. |
| std::array<fidl_channel_handle_metadata_t, kHandleAllocSize> read_handle_metadata; |
| ::fidl::IncomingMessage msg = ::fidl::MessageRead( |
| zx::unowned_channel(client_end.handle()), |
| read_storage.view(), |
| read_handles.data(), |
| read_handle_metadata.data(), |
| kHandleAllocSize, |
| ReadOptions{.discardable = true} |
| ); |
| if (msg.status() == ZX_ERR_BUFFER_TOO_SMALL) { |
| // Message size is unexpectedly larger than calculated. |
| // This can only be due to a newer version of the protocol defining a new event, |
| // whose size exceeds the maximum of known events in the current protocol. |
| return ::fidl::Status::UnexpectedMessage( |
| ZX_ERR_BUFFER_TOO_SMALL, ::fidl::internal::kErrorSyncEventBufferTooSmall); |
| } |
| if (!msg.ok()) { |
| return msg; |
| } |
| fidl_message_header_t* hdr = msg.header(); |
| switch (hdr->ordinal) { |
| {{- range .Events }} |
| case {{ .OrdinalName }}: { |
| ::fidl::unstable::DecodedMessage<{{ .WireTransactionalEvent }}> decoded{::std::move(msg)}; |
| if (!decoded.ok()) { |
| return ::fidl::Status(decoded); |
| } |
| {{- if .ResponseArgs }} |
| auto* primary = &decoded.PrimaryObject()->body; |
| {{- else }} |
| {{ .WireEvent }} empty_event; |
| auto* primary = &empty_event; |
| {{- end }} |
| got_transitional_ = false; |
| {{ .Name }}(primary); |
| if (got_transitional_) { |
| return ::fidl::Status::UnexpectedMessage( |
| ZX_ERR_NOT_SUPPORTED, ::fidl::internal::kErrorSyncEventUnhandledTransitionalEvent); |
| } |
| return ::fidl::Status::Ok(); |
| } |
| {{- end }} |
| default: { |
| return ::fidl::Status::UnknownOrdinal(); |
| } |
| } |
| } |
| |
| std::optional<::fidl::UnbindInfo> |
| {{ .WireEventDispatcher.NoLeading }}::DispatchEvent( |
| ::fidl::IncomingMessage& msg, |
| ::fidl::internal::IncomingTransportContext transport_context) { |
| switch (msg.header()->ordinal) { |
| {{- range .Events }} |
| case {{ .OrdinalName }}: |
| { |
| ::fidl::unstable::DecodedMessage<{{ .WireTransactionalEvent }}> decoded{std::move(msg)}; |
| if (!decoded.ok()) { |
| return ::fidl::UnbindInfo{decoded}; |
| } |
| if (event_handler()) { |
| {{- if .ResponseArgs }} |
| auto* primary = &decoded.PrimaryObject()->body; |
| {{- else }} |
| {{ .WireEvent }} empty_event; |
| auto* primary = &empty_event; |
| {{- end }} |
| event_handler()->{{ .Name }}(primary); |
| } |
| return std::nullopt; |
| } |
| {{- end }} |
| default: |
| break; |
| } |
| return ::fidl::UnbindInfo::UnknownOrdinal(); |
| } |
| |
| {{- else }}{{/* not .Transport.HasEvents */}} |
| ::fidl::Status {{ .WireSyncEventHandler.NoLeading }}::HandleOneEvent( |
| ::{{ .Transport.Namespace }}::UnownedClientEnd<{{ . }}> client_end) { |
| ZX_PANIC("events not supported for transport '{{ .Transport.Name }}'"); |
| } |
| std::optional<::fidl::UnbindInfo> |
| {{ .WireEventDispatcher.NoLeading }}::DispatchEvent( |
| fidl::IncomingMessage& msg, |
| internal::IncomingTransportContext transport_context) { |
| ZX_PANIC("events not supported for transport '{{ .Transport.Name }}'"); |
| } |
| {{- end }} |
| {{- EndifFuchsia }} |
| {{- end }} |
| |
| |
| |
| {{- define "Protocol:EventHandler:NaturalMessagingHeader" }} |
| {{- EnsureNamespace "" }} |
| {{- IfdefFuchsia }} |
| template<> |
| class {{ .NaturalEventHandlerInterface }} { |
| public: |
| {{ .NaturalEventHandlerInterface.Self }}() = default; |
| virtual ~{{ .NaturalEventHandlerInterface.Self }}() = default; |
| {{- range .Events -}} |
| {{- .Docs }} |
| virtual void {{ .Name }}({{ .NaturalEvent }}&) = 0; |
| {{- end }} |
| }; |
| |
| template<> |
| class {{ .NaturalAsyncEventHandler }} |
| : public {{ .NaturalEventHandlerInterface }}, public ::fidl::internal::AsyncEventHandler { |
| public: |
| {{ .NaturalAsyncEventHandler.Self }}() = default; |
| |
| {{- range .Events -}} |
| {{- .Docs }} |
| void {{ .Name }}({{ .NaturalEvent }}&) override {} |
| {{- end }} |
| }; |
| |
| template <> |
| class {{ .NaturalEventDispatcher }} final : |
| public ::fidl::internal::IncomingEventDispatcher<{{ .NaturalAsyncEventHandler }}> { |
| public: |
| explicit {{ .NaturalEventDispatcher.Self }}({{ .NaturalAsyncEventHandler }}* event_handler) |
| : IncomingEventDispatcher(event_handler) {} |
| |
| private: |
| std::optional<::fidl::UnbindInfo> DispatchEvent( |
| ::fidl::IncomingMessage& msg, |
| internal::IncomingTransportContext transport_context) override; |
| }; |
| {{- EndifFuchsia }} |
| {{- end }} |
| |
| |
| |
| {{- define "Protocol:EventHandler:NaturalMessagingSource" }} |
| {{- EnsureNamespace "" }} |
| {{- IfdefFuchsia }} |
| std::optional<::fidl::UnbindInfo> |
| {{ .NaturalEventDispatcher.NoLeading }}::DispatchEvent( |
| ::fidl::IncomingMessage& msg, |
| ::fidl::internal::IncomingTransportContext transport_context) { |
| {{- if .Events }} |
| switch (msg.header()->ordinal) { |
| {{- range .Events }} |
| case {{ .OrdinalName }}: |
| { |
| ::fitx::result decoded = ::fidl::internal::DecodeTransactionalMessage |
| {{- if .HasResponsePayload }}<{{ .ResponsePayload }}>{{ end -}}(std::move(msg)); |
| if (decoded.is_error()) { |
| return ::fidl::UnbindInfo(decoded.error_value()); |
| } |
| if (event_handler()) { |
| {{ .NaturalEvent }} event |
| {{- if .HasResponsePayload }} |
| = {{ .NaturalEventConverter }}::FromDomainObject(std::move(decoded.value())) |
| {{- end }}; |
| event_handler()->{{ .Name }}(event); |
| } |
| return std::nullopt; |
| } |
| {{- end }} |
| default: |
| break; |
| } |
| {{- end }} |
| return ::fidl::UnbindInfo::UnknownOrdinal(); |
| } |
| |
| {{- EndifFuchsia }} |
| {{- end }} |