1 // Copyright 2022 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 #ifndef GRPC_SRC_CORE_LIB_EVENT_ENGINE_POSIX_H
15 #define GRPC_SRC_CORE_LIB_EVENT_ENGINE_POSIX_H
16 
17 #include <grpc/support/port_platform.h>
18 
19 #include <memory>
20 
21 #include "absl/functional/any_invocable.h"
22 #include "absl/status/status.h"
23 #include "absl/status/statusor.h"
24 
25 #include <grpc/event_engine/endpoint_config.h>
26 #include <grpc/event_engine/event_engine.h>
27 #include <grpc/event_engine/memory_allocator.h>
28 #include <grpc/event_engine/slice_buffer.h>
29 
30 namespace grpc_event_engine {
31 namespace experimental {
32 
33 /// This defines an interface that posix specific EventEngines endpoints
34 /// may implement to support additional file descriptor related functionality.
35 class PosixEndpointWithFdSupport : public EventEngine::Endpoint {
36  public:
37   /// Returns the file descriptor associated with the posix endpoint.
38   virtual int GetWrappedFd() = 0;
39 
40   /// Returns if the Endpoint supports tracking events from errmsg queues on
41   /// posix systems.
42   virtual bool CanTrackErrors() = 0;
43 
44   /// Shutdown the endpoint. This function call should trigger execution of
45   /// any pending endpoint Read/Write callbacks with appropriate error
46   /// absl::Status. After this function call any subsequent endpoint
47   /// Read/Write operations until endpoint deletion should fail with an
48   /// appropriate absl::Status.
49   ///
50   /// \a on_release_fd - If specifed, the callback is invoked when the
51   /// endpoint is destroyed/deleted. The underlying file descriptor is
52   /// released instead of being closed. The callback will get the released
53   /// file descriptor as its argument if the release operation is successful.
54   /// Otherwise it would get an appropriate error status as its argument.
55   virtual void Shutdown(absl::AnyInvocable<void(absl::StatusOr<int> release_fd)>
56                             on_release_fd) = 0;
57 };
58 
59 /// Defines an interface that posix EventEngine listeners may implement to
60 /// support additional file descriptor related functionality.
61 class PosixListenerWithFdSupport : public EventEngine::Listener {
62  public:
63   /// Called when a posix listener bind operation completes. A single bind
64   /// operation may trigger creation of multiple listener fds. This callback
65   /// should be invoked once on each newly created and bound fd. If the
66   /// corresponding bind operation fails for a particular fd, this callback
67   /// must be invoked with a absl::FailedPreConditionError status.
68   ///
69   /// \a listener_fd - The listening socket fd that was bound to the specified
70   /// address.
71   using OnPosixBindNewFdCallback =
72       absl::AnyInvocable<void(absl::StatusOr<int> listener_fd)>;
73   /// Bind an address/port to this Listener.
74   ///
75   /// It is expected that multiple addresses/ports can be bound to this
76   /// Listener before Listener::Start has been called. Returns either the
77   /// bound port or an appropriate error status.
78   /// \a addr - The address to listen for incoming connections.
79   /// \a on_bind_new_fd The callback is invoked once for each newly bound
80   /// listener fd that may be created by this Bind operation.
81   virtual absl::StatusOr<int> BindWithFd(
82       const EventEngine::ResolvedAddress& addr,
83       OnPosixBindNewFdCallback on_bind_new_fd) = 0;
84 
85   /// Handle an externally accepted client connection. It must return an
86   /// appropriate error status in case of failure.
87   ///
88   /// This may be invoked to process a new client connection accepted by an
89   /// external listening fd.
90   /// \a listener_fd - The external listening socket fd that accepted the new
91   /// client connection.
92   /// \a fd - The socket file descriptor representing the new client
93   /// connection.
94   /// \a pending_data - If specified, it holds any pending data that may have
95   /// already been read over the externally accepted client connection.
96   /// Otherwise, it is assumed that no data has been read over the new client
97   /// connection.
98   virtual absl::Status HandleExternalConnection(int listener_fd, int fd,
99                                                 SliceBuffer* pending_data) = 0;
100 
101   /// Shutdown/stop listening on all bind Fds.
102   virtual void ShutdownListeningFds() = 0;
103 };
104 
105 /// Defines an interface that posix EventEngines may implement to
106 /// support additional file descriptor related functionality.
107 class PosixEventEngineWithFdSupport : public EventEngine {
108  public:
109   /// Creates a posix specific EventEngine::Endpoint from an fd which is already
110   /// assumed to be connected to a remote peer. \a fd - The connected socket
111   /// file descriptor. \a config - Additional configuration to applied to the
112   /// endpoint. \a memory_allocator - The endpoint may use the provided memory
113   /// allocator to track memory allocations.
114   virtual std::unique_ptr<PosixEndpointWithFdSupport> CreatePosixEndpointFromFd(
115       int fd, const EndpointConfig& config,
116       MemoryAllocator memory_allocator) = 0;
117 
118   /// Called when the posix listener has accepted a new client connection.
119   /// \a listener_fd - The listening socket fd that accepted the new client
120   /// connection.
121   /// \a endpoint - The EventEngine endpoint to handle data exchange over the
122   /// new client connection.
123   /// \a is_external - A boolean indicating whether the new client connection
124   /// is accepted by an external listener_fd or by a listener_fd that is
125   /// managed by the EventEngine listener.
126   /// \a memory_allocator - The callback may use the provided memory
127   /// allocator to handle memory allocation operations.
128   /// \a pending_data - If specified, it holds any pending data that may have
129   /// already been read over the new client connection. Otherwise, it is
130   /// assumed that no data has been read over the new client connection.
131   using PosixAcceptCallback = absl::AnyInvocable<void(
132       int listener_fd, std::unique_ptr<EventEngine::Endpoint> endpoint,
133       bool is_external, MemoryAllocator memory_allocator,
134       SliceBuffer* pending_data)>;
135 
136   /// Factory method to create a posix specific network listener / server with
137   /// fd support.
138   ///
139   /// Once a \a Listener is created and started, the \a on_accept callback will
140   /// be called once asynchronously for each established connection. This method
141   /// may return a non-OK status immediately if an error was encountered in any
142   /// synchronous steps required to create the Listener. In this case,
143   /// \a on_shutdown will never be called.
144   ///
145   /// If this method returns a Listener, then \a on_shutdown will be invoked
146   /// exactly once, when the Listener is shut down. The status passed to it will
147   /// indicate if there was a problem during shutdown.
148   ///
149   /// The provided \a MemoryAllocatorFactory is used to create \a
150   /// MemoryAllocators for Endpoint construction.
151   virtual absl::StatusOr<std::unique_ptr<PosixListenerWithFdSupport>>
152   CreatePosixListener(
153       PosixAcceptCallback on_accept,
154       absl::AnyInvocable<void(absl::Status)> on_shutdown,
155       const EndpointConfig& config,
156       std::unique_ptr<MemoryAllocatorFactory> memory_allocator_factory) = 0;
157 };
158 
159 }  // namespace experimental
160 }  // namespace grpc_event_engine
161 
162 #endif  // GRPC_SRC_CORE_LIB_EVENT_ENGINE_POSIX_H
163