18 _io_service(server->service()->GetAsioService()),
19 _strand(*_io_service),
20 _strand_required(_server->_strand_required),
21 _stream(*_io_service, *server->context()),
30 _send_buffer_flush_offset(0)
36 asio::socket_base::receive_buffer_size
option;
37 _stream.next_layer().get_option(
option);
43 asio::socket_base::send_buffer_size
option;
44 _stream.next_layer().get_option(
option);
50 asio::socket_base::receive_buffer_size
option((
int)
size);
56 asio::socket_base::send_buffer_size
option((
int)
size);
60void SSLSession::Connect()
63 if (_server->option_keep_alive())
64 socket().set_option(asio::ip::tcp::socket::keep_alive(
true));
66 if (_server->option_no_delay())
67 socket().set_option(asio::ip::tcp::no_delay(
true));
113 if (_send_buffer_main.empty())
123 if (_strand_required)
124 _stream.async_handshake(asio::ssl::stream_base::server, bind_executor(_strand, async_handshake_handler));
126 _stream.async_handshake(asio::ssl::stream_base::server, async_handshake_handler);
154 auto disconnected_session(this->shared_from_this());
155 _server->onDisconnected(disconnected_session);
158 auto self(this->shared_from_this());
159 auto unregister_session_handler = [
this, self]()
161 _server->UnregisterSession(
id());
163 if (_server->_strand_required)
164 _server->_strand.dispatch(unregister_session_handler);
166 _server->_io_service->dispatch(unregister_session_handler);
169bool SSLSession::DisconnectAsync(
bool dispatch)
175 auto self(this->shared_from_this());
176 auto disconnect_handler = [
this, self]()
187 auto async_shutdown_handler = [
this, self](std::error_code ec2) {
Disconnect(ec2); };
188 if (_strand_required)
189 _stream.async_shutdown(bind_executor(_strand, async_shutdown_handler));
191 _stream.async_shutdown(async_shutdown_handler);
193 if (_strand_required)
196 _strand.dispatch(disconnect_handler);
198 _strand.post(disconnect_handler);
203 _io_service->dispatch(disconnect_handler);
205 _io_service->post(disconnect_handler);
219 assert((
buffer !=
nullptr) &&
"Pointer to the buffer should not be null!");
231 _server->_bytes_sent +=
sent;
255 assert((
buffer !=
nullptr) &&
"Pointer to the buffer should not be null!");
261 std::condition_variable
cv;
262 asio::error_code error;
263 asio::system_timer
timer(_stream.get_executor());
268 std::unique_lock<std::mutex>
lck(
mtx);
279 timer.expires_from_now(timeout.chrono());
287 std::unique_lock<std::mutex>
lck(
mtx);
288 cv.wait(
lck, [&]() {
return done == 2; });
295 _server->_bytes_sent +=
sent;
302 if (error && (error != asio::error::timed_out))
319 assert((
buffer !=
nullptr) &&
"Pointer to the buffer should not be null!");
324 std::scoped_lock
locker(_send_lock);
327 bool send_required = _send_buffer_main.empty() || _send_buffer_flush.empty();
330 if (((_send_buffer_main.size() +
size) > _send_buffer_limit) && (_send_buffer_limit > 0))
332 SendError(asio::error::no_buffer_space);
338 _send_buffer_main.insert(_send_buffer_main.end(),
bytes,
bytes +
size);
341 _bytes_pending = _send_buffer_main.size();
355 if (_strand_required)
371 assert((
buffer !=
nullptr) &&
"Pointer to the buffer should not be null!");
383 _server->_bytes_received +=
received;
414 assert((
buffer !=
nullptr) &&
"Pointer to the buffer should not be null!");
420 std::condition_variable
cv;
421 asio::error_code error;
422 asio::system_timer
timer(_stream.get_executor());
427 std::unique_lock<std::mutex>
lck(
mtx);
438 timer.expires_from_now(timeout.chrono());
446 std::unique_lock<std::mutex>
lck(
mtx);
447 cv.wait(
lck, [&]() {
return done == 2; });
454 _server->_bytes_received +=
received;
461 if (error && (error != asio::error::timed_out))
483void SSLSession::TryReceive()
505 _bytes_received +=
size;
506 _server->_bytes_received +=
size;
512 if (_receive_buffer.size() ==
size)
515 if (((2 *
size) > _receive_buffer_limit) && (_receive_buffer_limit > 0))
517 SendError(asio::error::no_buffer_space);
522 _receive_buffer.resize(2 * size);
535 if (_strand_required)
536 _stream.async_read_some(asio::buffer(_receive_buffer.data(), _receive_buffer.size()), bind_executor(_strand, async_receive_handler));
538 _stream.async_read_some(asio::buffer(_receive_buffer.data(), _receive_buffer.size()), async_receive_handler);
541void SSLSession::TrySend()
550 if (_send_buffer_flush.empty())
552 std::scoped_lock locker(_send_lock);
555 _send_buffer_flush.swap(_send_buffer_main);
556 _send_buffer_flush_offset = 0;
560 _bytes_sending += _send_buffer_flush.size();
564 if (_send_buffer_flush.empty())
573 auto self(this->shared_from_this());
574 auto async_write_handler =
make_alloc_handler(_send_storage, [
this, self](std::error_code ec,
size_t size)
585 _bytes_sending -= size;
587 _server->_bytes_sent += size;
590 _send_buffer_flush_offset += size;
593 if (_send_buffer_flush_offset == _send_buffer_flush.size())
596 _send_buffer_flush.clear();
597 _send_buffer_flush_offset = 0;
613 if (_strand_required)
614 _stream.async_write_some(asio::buffer(_send_buffer_flush.data() + _send_buffer_flush_offset, _send_buffer_flush.size() - _send_buffer_flush_offset), bind_executor(_strand, async_write_handler));
616 _stream.async_write_some(asio::buffer(_send_buffer_flush.data() + _send_buffer_flush_offset, _send_buffer_flush.size() - _send_buffer_flush_offset), async_write_handler);
619void SSLSession::ClearBuffers()
622 std::scoped_lock locker(_send_lock);
625 _send_buffer_main.clear();
626 _send_buffer_flush.clear();
627 _send_buffer_flush_offset = 0;
635void SSLSession::ResetServer()
641void SSLSession::SendError(std::error_code ec)
644 if ((ec == asio::error::connection_aborted) ||
645 (ec == asio::error::connection_refused) ||
646 (ec == asio::error::connection_reset) ||
647 (ec == asio::error::eof) ||
648 (ec == asio::error::operation_aborted))
652 if (ec == asio::ssl::error::stream_truncated)
654 if (ec.category() == asio::error::get_ssl_category())
656 if ((ERR_GET_REASON(ec.value()) == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC) ||
657 (ERR_GET_REASON(ec.value()) == SSL_R_PROTOCOL_IS_SHUTDOWN) ||
658 (ERR_GET_REASON(ec.value()) == SSL_R_WRONG_VERSION_NUMBER))
662 onError(ec.value(), ec.category().name(), ec.message());
Asio allocate handler wrapper.
uint64_t bytes_pending() const noexcept
Get the number of bytes pending sent by the session.
virtual void onSent(size_t sent, size_t pending)
Handle buffer sent notification.
virtual bool SendAsync(const void *buffer, size_t size)
Send data to the client (asynchronous)
asio::ssl::stream< asio::ip::tcp::socket >::next_layer_type & socket() noexcept
Get the session socket.
void SetupReceiveBufferSize(size_t size)
Setup option: receive buffer size.
void SetupSendBufferSize(size_t size)
Setup option: send buffer size.
virtual void ReceiveAsync()
Receive data from the client (asynchronous)
virtual bool Disconnect()
Disconnect the session.
virtual void onConnected()
Handle session connected notification.
virtual void onReceived(const void *buffer, size_t size)
Handle buffer received notification.
size_t option_send_buffer_size() const
Get the option: send buffer size.
virtual size_t Send(const void *buffer, size_t size)
Send data to the client (synchronous)
SSLSession(const std::shared_ptr< SSLServer > &server)
Initialize the session with a given server.
virtual void onEmpty()
Handle empty send buffer notification.
bool IsConnected() const noexcept
Is the session connected?
virtual void onError(int error, const std::string &category, const std::string &message)
Handle error notification.
bool IsHandshaked() const noexcept
Is the session handshaked?
virtual size_t Receive(void *buffer, size_t size)
Receive data from the client (synchronous)
virtual void onHandshaked()
Handle session handshaked notification.
virtual void onDisconnected()
Handle session disconnected notification.
size_t option_receive_buffer_size() const
Get the option: receive buffer size.
AllocateHandler< THandler > make_alloc_handler(HandlerStorage &storage, THandler handler)
Helper function to wrap a handler object to add custom allocation.
C++ Server project definitions.