// Copyright Epic Games, Inc. All Rights Reserved. #pragma once ZEN_THIRD_PARTY_INCLUDES_START #include #if ZEN_USE_OPENSSL # include #endif ZEN_THIRD_PARTY_INCLUDES_END namespace zen::asio_http { /** * Traits for abstracting socket shutdown/close across plain TCP, Unix domain, and SSL sockets. * SSL sockets need lowest_layer() access and have different shutdown semantics. */ template struct SocketTraits { /// SSL sockets cannot use zero-copy file send (TransmitFile/sendfile) because /// those bypass the encryption layer. This flag lets templated code fall back /// to reading-into-memory for SSL connections. static constexpr bool IsSslSocket = false; static void ShutdownReceive(SocketType& S, std::error_code& Ec) { S.shutdown(asio::socket_base::shutdown_receive, Ec); } static void ShutdownBoth(SocketType& S, std::error_code& Ec) { S.shutdown(asio::socket_base::shutdown_both, Ec); } static void Close(SocketType& S, std::error_code& Ec) { S.close(Ec); } }; #if ZEN_USE_OPENSSL using SslSocket = asio::ssl::stream; template<> struct SocketTraits { static constexpr bool IsSslSocket = true; static void ShutdownReceive(SslSocket& S, std::error_code& Ec) { S.lowest_layer().shutdown(asio::socket_base::shutdown_receive, Ec); } static void ShutdownBoth(SslSocket& S, std::error_code& Ec) { // Best-effort SSL close_notify, then TCP shutdown S.shutdown(Ec); S.lowest_layer().shutdown(asio::socket_base::shutdown_both, Ec); } static void Close(SslSocket& S, std::error_code& Ec) { S.lowest_layer().close(Ec); } }; #endif } // namespace zen::asio_http