• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2024 The gRPC Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GRPC_SRC_CORE_LIB_EVENT_ENGINE_EXTENSIONS_SUPPORTS_FD_H
16 #define GRPC_SRC_CORE_LIB_EVENT_ENGINE_EXTENSIONS_SUPPORTS_FD_H
17 
18 #include <grpc/event_engine/event_engine.h>
19 #include <grpc/support/port_platform.h>
20 
21 #include "absl/functional/any_invocable.h"
22 #include "absl/status/statusor.h"
23 #include "absl/strings/string_view.h"
24 
25 namespace grpc_event_engine {
26 namespace experimental {
27 
28 class EndpointSupportsFdExtension {
29  public:
30   virtual ~EndpointSupportsFdExtension() = default;
EndpointExtensionName()31   static absl::string_view EndpointExtensionName() {
32     return "io.grpc.event_engine.extension.endpoint_supports_fd";
33   }
34   /// Returns the file descriptor associated with the posix endpoint.
35   virtual int GetWrappedFd() = 0;
36 
37   /// Shutdown the endpoint. This function call should trigger execution of
38   /// any pending endpoint Read/Write callbacks with appropriate error
39   /// absl::Status. After this function call any subsequent endpoint
40   /// Read/Write operations until endpoint deletion should fail with an
41   /// appropriate absl::Status.
42   ///
43   /// \a on_release_fd - If specified, the callback is invoked when the
44   /// endpoint is destroyed/deleted. The underlying file descriptor is
45   /// released instead of being closed. The callback will get the released
46   /// file descriptor as its argument if the release operation is successful.
47   /// Otherwise it would get an appropriate error status as its argument.
48   virtual void Shutdown(absl::AnyInvocable<void(absl::StatusOr<int> release_fd)>
49                             on_release_fd) = 0;
50 };
51 
52 class ListenerSupportsFdExtension {
53  public:
54   virtual ~ListenerSupportsFdExtension() = default;
EndpointExtensionName()55   static absl::string_view EndpointExtensionName() {
56     return "io.grpc.event_engine.extension.listener_supports_fd";
57   }
58   /// Called when a posix listener bind operation completes. A single bind
59   /// operation may trigger creation of multiple listener fds. This callback
60   /// should be invoked once on each newly created and bound fd. If the
61   /// corresponding bind operation fails for a particular fd, this callback
62   /// must be invoked with a absl::FailedPreConditionError status.
63   ///
64   /// \a listener_fd - The listening socket fd that was bound to the specified
65   /// address.
66   using OnPosixBindNewFdCallback =
67       absl::AnyInvocable<void(absl::StatusOr<int> listener_fd)>;
68   /// Bind an address/port to this Listener.
69   ///
70   /// It is expected that multiple addresses/ports can be bound to this
71   /// Listener before Listener::Start has been called. Returns either the
72   /// bound port or an appropriate error status.
73   /// \a addr - The address to listen for incoming connections.
74   /// \a on_bind_new_fd The callback is invoked once for each newly bound
75   /// listener fd that may be created by this Bind operation.
76   virtual absl::StatusOr<int> BindWithFd(
77       const EventEngine::ResolvedAddress& addr,
78       OnPosixBindNewFdCallback on_bind_new_fd) = 0;
79 
80   /// Handle an externally accepted client connection. It must return an
81   /// appropriate error status in case of failure.
82   ///
83   /// This may be invoked to process a new client connection accepted by an
84   /// external listening fd.
85   /// \a listener_fd - The external listening socket fd that accepted the new
86   /// client connection.
87   /// \a fd - The socket file descriptor representing the new client
88   /// connection.
89   /// \a pending_data - If specified, it holds any pending data that may have
90   /// already been read over the externally accepted client connection.
91   /// Otherwise, it is assumed that no data has been read over the new client
92   /// connection.
93   virtual absl::Status HandleExternalConnection(int listener_fd, int fd,
94                                                 SliceBuffer* pending_data) = 0;
95 
96   /// Shutdown/stop listening on all bind Fds.
97   virtual void ShutdownListeningFds() = 0;
98 };
99 
100 class EventEngineSupportsFdExtension {
101  public:
102   virtual ~EventEngineSupportsFdExtension() = default;
EndpointExtensionName()103   static absl::string_view EndpointExtensionName() {
104     return "io.grpc.event_engine.extension.event_engine_supports_fd";
105   }
106   /// Creates a posix specific EventEngine::Endpoint from an fd which is already
107   /// assumed to be connected to a remote peer. \a fd - The connected socket
108   /// file descriptor. \a config - Additional configuration to applied to the
109   /// endpoint. \a memory_allocator - The endpoint may use the provided memory
110   /// allocator to track memory allocations.
111   virtual std::unique_ptr<EventEngine::Endpoint> CreatePosixEndpointFromFd(
112       int fd, const EndpointConfig& config,
113       MemoryAllocator memory_allocator) = 0;
114 
115   /// Creates an EventEngine::Endpoint from an fd which is already assumed to be
116   /// connected to a remote peer. See \a CreatePosixEndpointFromFd for details.
117   /// This has the same behavior, but the \a memory_allocator is taken from the
118   /// EndpointConfig's resource quota.
119   virtual std::unique_ptr<EventEngine::Endpoint> CreateEndpointFromFd(
120       int fd, const EndpointConfig& config) = 0;
121 
122   /// Creates an EventEngine::Endpoint from a file descriptor that is configured
123   /// and bound locally but not yet connected to a remote peer. Returns a
124   /// connection handle to cancel the connection attempt if needed. Created
125   /// endpoint will be returned through `on_connect` callback.
126   /// \a fd - The socket file descriptor.
127   /// \a on_connect - The callback to invoke once fd is connected to peer.
128   /// \a addr - The remote peer to connect to. This should be the mapped peer
129   /// address returned when creating a new socket.
130   /// \a config - Additional configuration to be applied to the endpoint.
131   /// \a memory_allocator - The endpoint may use the provided memory allocator
132   /// to track memory allocations.
133   /// \a timeout - The timeout to use for the connection attempt.
134   virtual EventEngine::ConnectionHandle CreateEndpointFromUnconnectedFd(
135       int fd, EventEngine::OnConnectCallback on_connect,
136       const EventEngine::ResolvedAddress& addr, const EndpointConfig& config,
137       MemoryAllocator memory_allocator, EventEngine::Duration timeout) = 0;
138 
139   /// Called when the posix listener has accepted a new client connection.
140   /// \a listener_fd - The listening socket fd that accepted the new client
141   /// connection.
142   /// \a endpoint - The EventEngine endpoint to handle data exchange over the
143   /// new client connection.
144   /// \a is_external - A boolean indicating whether the new client connection
145   /// is accepted by an external listener_fd or by a listener_fd that is
146   /// managed by the EventEngine listener.
147   /// \a memory_allocator - The callback may use the provided memory
148   /// allocator to handle memory allocation operations.
149   /// \a pending_data - If specified, it holds any pending data that may have
150   /// already been read over the new client connection. Otherwise, it is
151   /// assumed that no data has been read over the new client connection.
152   using PosixAcceptCallback = absl::AnyInvocable<void(
153       int listener_fd, std::unique_ptr<EventEngine::Endpoint> endpoint,
154       bool is_external, MemoryAllocator memory_allocator,
155       SliceBuffer* pending_data)>;
156 
157   /// Factory method to create a posix specific network listener / server with
158   /// fd support.
159   ///
160   /// Once a \a Listener is created and started, the \a on_accept callback will
161   /// be called once asynchronously for each established connection. This method
162   /// may return a non-OK status immediately if an error was encountered in any
163   /// synchronous steps required to create the Listener. In this case,
164   /// \a on_shutdown will never be called.
165   ///
166   /// If this method returns a Listener, then \a on_shutdown will be invoked
167   /// exactly once, when the Listener is shut down. The status passed to it will
168   /// indicate if there was a problem during shutdown.
169   ///
170   /// The provided \a MemoryAllocatorFactory is used to create \a
171   /// MemoryAllocators for Endpoint construction.
172   virtual absl::StatusOr<std::unique_ptr<EventEngine::Listener>>
173   CreatePosixListener(
174       PosixAcceptCallback on_accept,
175       absl::AnyInvocable<void(absl::Status)> on_shutdown,
176       const EndpointConfig& config,
177       std::unique_ptr<MemoryAllocatorFactory> memory_allocator_factory) = 0;
178 };
179 
180 }  // namespace experimental
181 }  // namespace grpc_event_engine
182 
183 #endif  // GRPC_SRC_CORE_LIB_EVENT_ENGINE_EXTENSIONS_SUPPORTS_FD_H
184