/* * Copyright (c) 2017-2023 zhllxt * * author : zhllxt * email : 37792738@qq.com * * Distributed under the Boost Software License, Version 1.0. (See accompanying * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */ #ifndef __ASIO2_UDP_RECV_OP_HPP__ #define __ASIO2_UDP_RECV_OP_HPP__ #if defined(_MSC_VER) && (_MSC_VER >= 1200) #pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include #include #include #include namespace asio2::detail { template class udp_recv_op { public: /** * @brief constructor */ udp_recv_op() noexcept {} /** * @brief destructor */ ~udp_recv_op() = default; protected: template void _udp_post_recv(std::shared_ptr this_ptr, std::shared_ptr> ecs) { derived_t& derive = static_cast(*this); ASIO2_ASSERT(derive.io_->running_in_this_thread()); if (!derive.is_started()) { if (derive.state_ == state_t::started) { derive._do_disconnect(asio2::get_last_error(), std::move(this_ptr)); } return; } #if defined(_DEBUG) || defined(DEBUG) ASIO2_ASSERT(derive.post_recv_counter_.load() == 0); derive.post_recv_counter_++; #endif ASIO2_ASSERT(derive.reading_ == false); derive.reading_ = true; derive.socket().async_receive(derive.buffer().prepare(derive.buffer().pre_size()), make_allocator(derive.rallocator(), [&derive, this_ptr = std::move(this_ptr), ecs = std::move(ecs)] (const error_code & ec, std::size_t bytes_recvd) mutable { #if defined(_DEBUG) || defined(DEBUG) derive.post_recv_counter_--; #endif derive.reading_ = false; derive._handle_recv(ec, bytes_recvd, std::move(this_ptr), std::move(ecs)); })); } template inline void _udp_do_handle_recv( const error_code& ec, std::size_t bytes_recvd, std::shared_ptr& this_ptr, std::shared_ptr>& ecs) { using condition_lowest_type = typename ecs_t::condition_lowest_type; derived_t& derive = static_cast(*this); if (!ec) { std::string_view data = std::string_view(static_cast (derive.buffer().data().data()), bytes_recvd); if constexpr (!std::is_same_v::condition_lowest_type, use_kcp_t>) { derive._fire_recv(this_ptr, ecs, data); } else { if (derive.kcp_stream_) { derive.kcp_stream_->_kcp_handle_recv(ec, data, this_ptr, ecs); } else { ASIO2_ASSERT(false); derive._do_disconnect(asio::error::invalid_argument, this_ptr); derive._stop_readend_timer(std::move(this_ptr)); } } } else { ASIO2_LOG_DEBUG("_udp_handle_recv with error: {} {}", ec.value(), ec.message()); if (ec == asio::error::eof) { ASIO2_ASSERT(bytes_recvd == 0); if (bytes_recvd) { // http://www.purecpp.cn/detail?id=2303 ASIO2_LOG_INFOR("_udp_handle_recv with eof: {}", bytes_recvd); } } } } template inline void _udp_session_handle_recv( const error_code& ec, std::size_t bytes_recvd, std::shared_ptr& this_ptr, std::shared_ptr>& ecs) { derived_t& derive = static_cast(*this); derive._udp_do_handle_recv(ec, bytes_recvd, this_ptr, ecs); } template void _udp_client_handle_recv( const error_code& ec, std::size_t bytes_recvd, std::shared_ptr& this_ptr, std::shared_ptr>& ecs) { derived_t& derive = static_cast(*this); if (ec == asio::error::operation_aborted || ec == asio::error::connection_refused) { derive._do_disconnect(ec, this_ptr); derive._stop_readend_timer(std::move(this_ptr)); return; } derive.buffer().commit(bytes_recvd); derive._udp_do_handle_recv(ec, bytes_recvd, this_ptr, ecs); derive.buffer().consume(derive.buffer().size()); if (bytes_recvd == derive.buffer().pre_size()) { derive.buffer().pre_size((std::min)(derive.buffer().pre_size() * 2, derive.buffer().max_size())); } derive._post_recv(this_ptr, ecs); } template void _udp_handle_recv( const error_code& ec, std::size_t bytes_recvd, std::shared_ptr& this_ptr, std::shared_ptr>& ecs) { derived_t& derive = static_cast(*this); ASIO2_ASSERT(derive.io_->running_in_this_thread()); set_last_error(ec); if (!derive.is_started()) { if (derive.state_ == state_t::started) { derive._do_disconnect(ec, this_ptr); } derive._stop_readend_timer(std::move(this_ptr)); return; } // every times recv data,we update the last alive time. if (!ec) { derive.update_alive_time(); } if constexpr (args_t::is_session) { derive._udp_session_handle_recv(ec, bytes_recvd, this_ptr, ecs); } else { derive._udp_client_handle_recv(ec, bytes_recvd, this_ptr, ecs); } } protected: }; } #endif // !__ASIO2_UDP_RECV_OP_HPP__