1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
|