uvco 0.1
Loading...
Searching...
No Matches
uvco::StreamServerBase< UvStreamType, StreamType > Class Template Reference

#include <stream_server_base.h>

Classes

struct  ConnectionAwaiter_

Public Member Functions

 StreamServerBase (const StreamServerBase &)=delete
 StreamServerBase (StreamServerBase &&)=default
StreamServerBaseoperator= (const StreamServerBase &)=delete
StreamServerBaseoperator= (StreamServerBase &&)=default
 ~StreamServerBase ()
MultiPromise< StreamType > listen (int backlog=128)
AddressHandle getSockname () const
 Get the address the server is bound to.
void close ()

Protected Member Functions

 StreamServerBase (std::unique_ptr< UvStreamType > socket)

Protected Attributes

std::unique_ptr< UvStreamType > socket_

Static Private Member Functions

static void onNewConnection (uv_stream_t *stream, uv_status status)
 Called by libuv when a new connection arrives.

Detailed Description

template<typename UvStreamType, typename StreamType>
class uvco::StreamServerBase< UvStreamType, StreamType >

Not for use in user code; base class for e.g. UnixServer and TcpServer.

Because accepting connections looks the same for Unix and TCP servers, the behavior is defined here and shared by both. However, the implementation must be generic over the stream type, so the actual stream type is a template parameter.

Constructor & Destructor Documentation

◆ StreamServerBase() [1/3]

template<typename UvStreamType, typename StreamType>
uvco::StreamServerBase< UvStreamType, StreamType >::StreamServerBase ( const StreamServerBase< UvStreamType, StreamType > & )
delete

◆ StreamServerBase() [2/3]

template<typename UvStreamType, typename StreamType>
uvco::StreamServerBase< UvStreamType, StreamType >::StreamServerBase ( StreamServerBase< UvStreamType, StreamType > && )
default

◆ ~StreamServerBase()

template<typename UvStreamType, typename StreamType>
uvco::StreamServerBase< UvStreamType, StreamType >::~StreamServerBase ( )
119 {
120 // Quasi-sync method.
121 close();
122}
void close()
Definition stream_server_base_impl.cc:125

◆ StreamServerBase() [3/3]

template<typename UvStreamType, typename StreamType>
uvco::StreamServerBase< UvStreamType, StreamType >::StreamServerBase ( std::unique_ptr< UvStreamType > socket)
inlineexplicitprotected
Definition stream_server_base.h:35
std::unique_ptr< UvStreamType > socket_
Definition stream_server_base.h:66

Member Function Documentation

◆ close()

template<typename UvStreamType, typename StreamType>
void uvco::StreamServerBase< UvStreamType, StreamType >::close ( )

Close server and stop accepting client connections. As opposed to many other close() methods, it's synchronous, and therefore needs not be called, as the destructor calls it.

Internally it makes use of the quasi-sync behavior of closeHandle(), making it actually more robust than a coroutine (against dropping etc.)

125 {
126 if (socket_ != nullptr && !dataIsNull(socket_.get())) {
128 // Resume listener coroutine and tell it to exit.
129 // If awaiter == nullptr, one of two things is true:
130 // 1. listener is currently not running
131 // 2. listener has yielded and is suspended there: the listener generator
132 // will be cancelled when its MultiPromise is dropped.
133 awaiter->stop();
134 }
135 if (socket_ != nullptr && !isClosed(socket_.get())) {
136 // closeHandle takes care of freeing the memory if its own promise is
137 // dropped.
138 closeHandle(socket_.release());
139 }
140}
bool isClosed(const Handle *h)
Definition close.h:19
void closeHandle(Handle *handle, void(*closer)(CloserArg *, void(*)(uv_handle_t *)))
Definition close.h:37
Into * getData(const Handle *handle)
Obtain data pointer set on handle with nullptr check and type cast.
Definition internal_utils.h:42
bool dataIsNull(Handle *handle)
Check if handle data is null.
Definition internal_utils.h:101

◆ getSockname()

template<typename UvStreamType, typename StreamType>
AddressHandle uvco::StreamServerBase< UvStreamType, StreamType >::getSockname ( ) const
nodiscard

Get the address the server is bound to.

193 {
195 struct sockaddr_storage addr{};
196 int addrLen = sizeof(addr);
197 const uv_status status =
198 uv_tcp_getsockname(socket_.get(), (struct sockaddr *)&addr, &addrLen);
199 if (status != 0) {
200 throw UvcoException{status, "StreamServerBase::getSockname() failed"};
201 }
202 return AddressHandle{(struct sockaddr *)&addr};
203 } else if constexpr (std::is_same_v<UvStreamType, uv_pipe_t>) {
204 throw UvcoException{
205 UV_ENOSYS,
206 "StreamServerBase::getSockname() not implemented for uv_pipe_t"};
207 } else {
208 static_assert(false);
209 }
210}

◆ listen()

template<typename UvStreamType, typename StreamType>
MultiPromise< StreamType > uvco::StreamServerBase< UvStreamType, StreamType >::listen ( int backlog = 128)

Return client connections as clients connect.

Raises exceptions if errors occur during accepting or listening.

This generator may not be co_awaited on after having called close().

144 {
147
148 const uv_status listenStatus =
151 if (listenStatus != 0) {
153 "StreamServerBase::listen(): failed to listen"};
154 }
155
156 while (true) {
157 const bool acceptOk = co_await awaiter;
158 if (!acceptOk) {
159 // At this point, do not touch socket_->data anymore!
160 // This is the result of ConnectionAwaiter_::stop(), and
161 // data points to a CloseAwaiter_ object.
162 break;
163 }
164
165 for (auto it = awaiter.accepted_.begin(); it != awaiter.accepted_.end();
166 it++) {
167 auto &streamSlot = *it;
168
169 if (streamSlot.index() == 0) {
171 BOOST_ASSERT(status != 0);
172 // When the error is handled, the user code can again call listen()
173 // and will process the remaining connections. Therefore, first remove
174 // the already processed connections.
175 awaiter.accepted_.erase(awaiter.accepted_.begin(), it);
176 throw UvcoException{status,
177 "UnixStreamServer failed to accept a connection!"};
178 } else {
179 // Awkward handlign: if the returned MultiPromise is dropped, we will
180 // never return from co_yield. However, dropping may happen after
181 // calling `close()`, so we cannot rely on socket_ still existing.
182 //
183 // `close()` also relies on whether `socket_->data` is `nullptr` or not
184 // to decide if the socket has been closed already.
186 }
187 }
188 awaiter.accepted_.clear();
189 }
190}
Definition stream_server_base_impl.cc:32

◆ onNewConnection()

template<typename UvStreamType, typename StreamType>
void uvco::StreamServerBase< UvStreamType, StreamType >::onNewConnection ( uv_stream_t * stream,
uv_status status )
staticprivate

Called by libuv when a new connection arrives.

89 {
90 const auto *server = (UvStreamType *)stream;
92 if (connectionAwaiter == nullptr) {
93 return;
94 }
96
97 if (status == 0) {
100 const uv_status acceptStatus =
102 if (acceptStatus == 0) {
103 connectionAwaiter->accepted_.emplace_back(
105 } else {
106 connectionAwaiter->accepted_.emplace_back(acceptStatus);
107 }
108 } else {
109 connectionAwaiter->accepted_.emplace_back(status);
110 }
111
112 if (connectionAwaiter->handle_ != nullptr) {
114 connectionAwaiter->handle_ = nullptr;
115 }
116}
static void enqueue(std::coroutine_handle<> handle)
Definition loop.cc:94
static void init(uv_loop_t *, UvStreamType *)
Definition stream_server_base.h:24

◆ operator=() [1/2]

template<typename UvStreamType, typename StreamType>
StreamServerBase & uvco::StreamServerBase< UvStreamType, StreamType >::operator= ( const StreamServerBase< UvStreamType, StreamType > & )
delete

◆ operator=() [2/2]

template<typename UvStreamType, typename StreamType>
StreamServerBase & uvco::StreamServerBase< UvStreamType, StreamType >::operator= ( StreamServerBase< UvStreamType, StreamType > && )
default

Member Data Documentation

◆ socket_

template<typename UvStreamType, typename StreamType>
std::unique_ptr<UvStreamType> uvco::StreamServerBase< UvStreamType, StreamType >::socket_
protected

The documentation for this class was generated from the following files: