aboutsummaryrefslogtreecommitdiff
path: root/src/zenhttp/servers/asio_socket_traits.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/zenhttp/servers/asio_socket_traits.h')
-rw-r--r--src/zenhttp/servers/asio_socket_traits.h54
1 files changed, 54 insertions, 0 deletions
diff --git a/src/zenhttp/servers/asio_socket_traits.h b/src/zenhttp/servers/asio_socket_traits.h
new file mode 100644
index 000000000..25aeaa24e
--- /dev/null
+++ b/src/zenhttp/servers/asio_socket_traits.h
@@ -0,0 +1,54 @@
+// Copyright Epic Games, Inc. All Rights Reserved.
+
+#pragma once
+
+ZEN_THIRD_PARTY_INCLUDES_START
+#include <asio.hpp>
+#if ZEN_USE_OPENSSL
+# include <asio/ssl.hpp>
+#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<typename SocketType>
+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<asio::ip::tcp::socket>;
+
+template<>
+struct SocketTraits<SslSocket>
+{
+ 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