From c329e963c24661bceb087ab1eca58573114fb5e2 Mon Sep 17 00:00:00 2001 From: Coldwings Date: Thu, 18 Jan 2024 15:18:15 +0800 Subject: [PATCH 1/9] Fix HTTPFSv2 using proxy (#336) Signed-off-by: Coldwings --- fs/httpfs/httpfs_v2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/httpfs/httpfs_v2.cpp b/fs/httpfs/httpfs_v2.cpp index 5aaff947..eaef3f3c 100644 --- a/fs/httpfs/httpfs_v2.cpp +++ b/fs/httpfs/httpfs_v2.cpp @@ -151,8 +151,8 @@ class HttpFile_v2 : public fs::VirtualReadOnlyFile { again: estring url; url.appends(m_url, "?", m_url_param); - op.req.reset(net::http::Verb::GET, url); op.set_enable_proxy(m_fs->get_client()->has_proxy()); + op.req.reset(net::http::Verb::GET, url, op.enable_proxy); op.req.headers.merge(m_common_header); op.req.headers.range(offset, offset + length - 1); op.req.headers.content_length(0); From 211ebea1b210467b1c47e541dbed467f83e86da6 Mon Sep 17 00:00:00 2001 From: Coldwings Date: Sun, 18 Feb 2024 11:19:52 +0800 Subject: [PATCH 2/9] FIX httpfs_v2 common header for file able to replace by ioctl (#351) FIX httpfs common header for file able to replace by ioctl --- fs/httpfs/httpfs_v2.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/httpfs/httpfs_v2.cpp b/fs/httpfs/httpfs_v2.cpp index eaef3f3c..57e07072 100644 --- a/fs/httpfs/httpfs_v2.cpp +++ b/fs/httpfs/httpfs_v2.cpp @@ -103,7 +103,7 @@ class HttpFs_v2 : public fs::IFileSystem { class HttpFile_v2 : public fs::VirtualReadOnlyFile { public: std::string m_url; - net::http::CommonHeaders<> m_common_header; + unordered_map_string_key m_common_header; HttpFs_v2* m_fs; struct stat m_stat; uint64_t m_stat_gettime = 0; @@ -153,7 +153,8 @@ class HttpFile_v2 : public fs::VirtualReadOnlyFile { url.appends(m_url, "?", m_url_param); op.set_enable_proxy(m_fs->get_client()->has_proxy()); op.req.reset(net::http::Verb::GET, url, op.enable_proxy); - op.req.headers.merge(m_common_header); + for (auto &kv : m_common_header) + op.req.headers.insert(kv.first, kv.second); op.req.headers.range(offset, offset + length - 1); op.req.headers.content_length(0); op.timeout = tmo.timeout(); @@ -228,9 +229,10 @@ class HttpFile_v2 : public fs::VirtualReadOnlyFile { return m_exists ? 0 : -1; } - //TODO: 这里是否需要考虑m_common_header被打爆的问题? void add_header(va_list args) { - m_common_header.insert(va_arg(args, const char*), va_arg(args, const char*)); + auto k = va_arg(args, const char*); + auto v = va_arg(args, const char*); + m_common_header[k] = v; } void add_url_param(va_list args) { m_url_param = va_arg(args, const char*); } From c70d69811d51870f40774051724db8515fa6cec6 Mon Sep 17 00:00:00 2001 From: Coldwings Date: Wed, 21 Feb 2024 10:58:17 +0800 Subject: [PATCH 3/9] ALog Prologue now keeps only last part of source path (filename), using us timestamps (#364) * Fix alog namedvalue print character array Signed-off-by: Coldwings * ALog prologue keeps only filename, uses us timestamp Signed-off-by: Coldwings * make `update_now` returns timeval, so as `alog_update_now()` Signed-off-by: Coldwings * Fix `make_named_value` Signed-off-by: Coldwings * `Prologue use const char* for string instead of uint64_t Signed-off-by: Coldwings * `prologue` with constexpr constructor Signed-off-by: Coldwings * prevent warning for make_named_value in clang Signed-off-by: Coldwings --------- Signed-off-by: Coldwings --- common/alog.cpp | 19 ++++++++++--------- common/alog.h | 38 ++++++++++++++++++++++++-------------- thread/thread.cpp | 21 +++++++++++++-------- 3 files changed, 47 insertions(+), 31 deletions(-) diff --git a/common/alog.cpp b/common/alog.cpp index 4d5a7aad..e371b801 100644 --- a/common/alog.cpp +++ b/common/alog.cpp @@ -228,11 +228,6 @@ struct tm* alog_update_time(time_t now) return &alog_time; } -static struct tm* alog_update_time() -{ - return alog_update_time(time(0) - timezone); -} - class LogOutputFile final : public BaseLogOutput { public: uint64_t log_file_size_limit = 0; @@ -494,28 +489,34 @@ static inline ALogInteger DEC_W2P0(uint64_t x) return DEC(x).width(2).padding('0'); } +namespace photon { +struct timeval alog_update_now(); +} + LogBuffer& operator << (LogBuffer& log, const Prologue& pro) { #ifdef LOG_BENCHMARK auto t = &alog_time; #else - auto t = alog_update_time(); + auto ts = photon::alog_update_now(); + auto t = alog_update_time(ts.tv_sec - timezone); #endif log.printf(t->tm_year, '/'); log.printf(DEC_W2P0(t->tm_mon), '/'); log.printf(DEC_W2P0(t->tm_mday), ' '); log.printf(DEC_W2P0(t->tm_hour), ':'); log.printf(DEC_W2P0(t->tm_min), ':'); - log.printf(DEC_W2P0(t->tm_sec)); + log.printf(DEC_W2P0(t->tm_sec), '.'); + log.printf(DEC(ts.tv_usec).width(6).padding('0')); static const char levels[] = "|DEBUG|th=|INFO |th=|WARN |th=|ERROR|th=|FATAL|th=|TEMP |th=|AUDIT|th="; log.reserved = pro.level; log.printf(ALogString(&levels[pro.level * 10], 10)); log.printf(photon::CURRENT, '|'); if (pro.level != ALOG_AUDIT) { - log.printf(ALogString((char*)pro.addr_file, pro.len_file), ':'); + log.printf(ALogString(pro.addr_file, pro.len_file), ':'); log.printf(pro.line, '|'); - log.printf(ALogString((char*)pro.addr_func, pro.len_func), ':'); + log.printf(ALogString(pro.addr_func, pro.len_func), ':'); } return log; } diff --git a/common/alog.h b/common/alog.h index fe8ff2f0..247bdbd5 100644 --- a/common/alog.h +++ b/common/alog.h @@ -343,9 +343,19 @@ struct LogBuffer : public ALogBuffer struct Prologue { - uint64_t addr_func, addr_file; + const char *addr_func, *addr_file; int len_func, len_file; int line, level; + + template + constexpr Prologue(const char (&addr_func_)[N], FILEN addr_file_, int line_, + int level_) + : addr_func(addr_func_), + addr_file(addr_file_.chars), + len_func(N - 1), + len_file(addr_file_.len - 1), + line(line_), + level(level_) {} }; LogBuffer& operator << (LogBuffer& log, const Prologue& pro); @@ -441,25 +451,19 @@ struct LogBuilder { } }; -#if __GNUC__ >= 9 -#define DEFINE_PROLOGUE(level, prolog) \ - static constexpr const char* _prologue_func = __func__; \ - const static Prologue prolog{ \ - (uint64_t) _prologue_func, (uint64_t)__FILE__, sizeof(__func__) - 1, \ - sizeof(__FILE__) - 1, __LINE__, level}; -#else -#define DEFINE_PROLOGUE(level, prolog) \ - const static Prologue prolog{ \ - (uint64_t) __func__, (uint64_t)__FILE__, sizeof(__func__) - 1, \ - sizeof(__FILE__) - 1, __LINE__, level}; -#endif +#define DEFINE_PROLOGUE(level) \ + auto _prologue_file_r = TSTRING(__FILE__).reverse(); \ + auto _partial_file = \ + ConstString::TSpliter<'/', ' ', \ + decltype(_prologue_file_r)>::Current::reverse(); \ + constexpr static Prologue prolog(__func__, _partial_file, __LINE__, level); #define _IS_LITERAL_STRING(x) \ (sizeof(#x) > 2 && (#x[0] == '"') && (#x[sizeof(#x) - 2] == '"')) #define __LOG__(logger, level, first, ...) \ ({ \ - DEFINE_PROLOGUE(level, prolog); \ + DEFINE_PROLOGUE(level); \ auto __build_lambda__ = [&](ILogOutput* __output_##__LINE__) { \ if (_IS_LITERAL_STRING(first)) { \ return __log__(level, __output_##__LINE__, prolog, \ @@ -523,6 +527,12 @@ inline NamedValue make_named_value(const char (&name)[N], T&& value) return NamedValue {ALogStringL(name), std::forward(value)}; } +template +inline NamedValue make_named_value(const char (&name)[N], + char (&value)[M]) { + return {ALogStringL(name), alog_forwarding(value)}; +} + #define VALUE(x) make_named_value(#x, x) template diff --git a/thread/thread.cpp b/thread/thread.cpp index d2a85426..c3de95b5 100644 --- a/thread/thread.cpp +++ b/thread/thread.cpp @@ -1035,7 +1035,7 @@ R"( volatile uint64_t now; static std::atomic ts_updater(0); - static inline uint64_t update_now() + static inline struct timeval update_now() { #if defined(__x86_64__) && defined(__linux__) && defined(ENABLE_MIMIC_VDSO) if (likely(__mimic_vdso_time_x86)) @@ -1047,7 +1047,7 @@ R"( nnow *= 1000 * 1000; nnow += tv.tv_usec; now = nnow; - return nnow; + return tv; } __attribute__((always_inline)) static inline uint32_t _rdtsc() @@ -1072,23 +1072,28 @@ R"( #endif } static uint32_t last_tsc = 0; - static inline uint64_t if_update_now(bool accurate = false) { + static inline void if_update_now(bool accurate = false) { #if defined(__x86_64__) && defined(__linux__) && defined(ENABLE_MIMIC_VDSO) if (likely(__mimic_vdso_time_x86)) { return photon::now = __mimic_vdso_time_x86.get_now(accurate); } #endif if (likely(ts_updater.load(std::memory_order_relaxed))) { - return photon::now; + return; + } + if (unlikely(accurate)) { + update_now(); + return; } - if (unlikely(accurate)) - return update_now(); uint32_t tsc = _rdtsc(); if (unlikely(last_tsc != tsc)) { last_tsc = tsc; - return update_now(); + update_now(); } - return photon::now; + } + struct timeval alog_update_now() { + last_tsc = _rdtsc(); + return update_now(); } int timestamp_updater_init() { if (!ts_updater) { From fb6eb1f02802d168f05a794272172b980e8f7576 Mon Sep 17 00:00:00 2001 From: Lanzheng Liu Date: Wed, 21 Feb 2024 12:01:19 +0800 Subject: [PATCH 4/9] fix readdir for localfs Signed-off-by: Lanzheng Liu --- fs/localfs.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/localfs.cpp b/fs/localfs.cpp index 2c9dfbc7..e133bfad 100644 --- a/fs/localfs.cpp +++ b/fs/localfs.cpp @@ -294,6 +294,8 @@ namespace fs ::DIR* dirp; ::dirent* direntp; long loc; + ::dirent m_dirent; + LocalDIR(::DIR* dirp) : dirp(dirp) { next(); @@ -313,6 +315,10 @@ namespace fs } virtual dirent* get() override { + if (direntp) { + memcpy(&m_dirent, direntp, sizeof(m_dirent)); + return &m_dirent; + } return direntp; } virtual int next() override From d2e6eb55af5d7176bcc2f3a11646b8edc5855fcb Mon Sep 17 00:00:00 2001 From: Coldwings Date: Wed, 21 Feb 2024 13:31:39 +0800 Subject: [PATCH 5/9] Fix prologue file field length (#369) Signed-off-by: Coldwings --- common/alog.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/alog.h b/common/alog.h index 247bdbd5..f019ba86 100644 --- a/common/alog.h +++ b/common/alog.h @@ -353,7 +353,7 @@ struct Prologue : addr_func(addr_func_), addr_file(addr_file_.chars), len_func(N - 1), - len_file(addr_file_.len - 1), + len_file(addr_file_.len), line(line_), level(level_) {} }; From 9caa491464f8c2ee664009317fc31cbe2c7c7855 Mon Sep 17 00:00:00 2001 From: Coldwings Date: Fri, 23 Feb 2024 10:04:47 +0800 Subject: [PATCH 6/9] Fix: make_named_tuple maked ref to temporary alogstring (#375) Signed-off-by: Coldwings --- common/alog.h | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/common/alog.h b/common/alog.h index f019ba86..c3a7de17 100644 --- a/common/alog.h +++ b/common/alog.h @@ -528,24 +528,18 @@ inline NamedValue make_named_value(const char (&name)[N], T&& value) } template -inline NamedValue make_named_value(const char (&name)[N], - char (&value)[M]) { - return {ALogStringL(name), alog_forwarding(value)}; +inline NamedValue make_named_value(const char (&name)[N], + char (&value)[M]) { + return {ALogStringL(name), value}; } #define VALUE(x) make_named_value(#x, x) -template -inline LogBuffer& operator << (LogBuffer& log, const NamedValue& v) -{ +template +inline LogBuffer& operator<<(LogBuffer& log, const NamedValue& v) { return log.printf('[', v.name, '=', v.value, ']'); } -inline LogBuffer& operator << (LogBuffer& log, const NamedValue& v) -{ - return log.printf('[', v.name, '=', '"', v.value, '"', ']'); -} - // output a log message, set errno, then return a value // keep errno unchaged if new_errno == 0 #define LOG_ERROR_RETURN(new_errno, retv, ...) { \ From 06b83ac4f29be93e7ec4ce6a054ff570c9932c88 Mon Sep 17 00:00:00 2001 From: Coldwings Date: Fri, 1 Mar 2024 09:48:42 +0800 Subject: [PATCH 7/9] Fix compile in gcc492 (#384) * Fix compile in gcc492, ignore some designed warning with diagnostic pragma Signed-off-by: Coldwings * Only add no-packed-bitfield-compat for GCC Signed-off-by: Coldwings --------- Signed-off-by: Coldwings --- CMakeLists.txt | 4 ++++ common/alog.h | 13 +++++++------ examples/perf/net-perf.cpp | 1 - net/http/client.cpp | 4 ++-- net/http/headers.cpp | 3 +++ net/utils.cpp | 3 +++ thread/thread.cpp | 3 +++ 7 files changed, 22 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1167c143..b3f88863 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,10 @@ set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) set(CMAKE_POSITION_INDEPENDENT_CODE ON) set(CMAKE_BUILD_PARALLEL_LEVEL ${NumCPU}) +if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-packed-bitfield-compat") +endif() + if (${ARCH} STREQUAL x86_64) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2") elseif (${ARCH} STREQUAL aarch64) diff --git a/common/alog.h b/common/alog.h index c3a7de17..c1ca1790 100644 --- a/common/alog.h +++ b/common/alog.h @@ -347,13 +347,13 @@ struct Prologue int len_func, len_file; int line, level; - template - constexpr Prologue(const char (&addr_func_)[N], FILEN addr_file_, int line_, - int level_) + template + constexpr Prologue(const char (&addr_func_)[N], const char (&addr_file_)[M], + int line_, int level_) : addr_func(addr_func_), - addr_file(addr_file_.chars), + addr_file(addr_file_), len_func(N - 1), - len_file(addr_file_.len), + len_file(M - 1), line(line_), level(level_) {} }; @@ -456,7 +456,8 @@ struct LogBuilder { auto _partial_file = \ ConstString::TSpliter<'/', ' ', \ decltype(_prologue_file_r)>::Current::reverse(); \ - constexpr static Prologue prolog(__func__, _partial_file, __LINE__, level); + constexpr static Prologue prolog(__func__, _partial_file.chars, __LINE__, \ + level); #define _IS_LITERAL_STRING(x) \ (sizeof(#x) > 2 && (#x[0] == '"') && (#x[sizeof(#x) - 2] == '"')) diff --git a/examples/perf/net-perf.cpp b/examples/perf/net-perf.cpp index c2b94edd..eb24e28a 100644 --- a/examples/perf/net-perf.cpp +++ b/examples/perf/net-perf.cpp @@ -35,7 +35,6 @@ DEFINE_uint64(port, 9527, "port"); DEFINE_uint64(buf_size, 512, "buffer size"); DEFINE_uint64(vcpu_num, 1, "server vcpu num. Increase this value to enable multi-vcpu scheduling"); -static int event_engine = 0; static bool stop_test = false; static uint64_t qps = 0; static uint64_t time_cost = 0; diff --git a/net/http/client.cpp b/net/http/client.cpp index b78203d8..df349ba3 100644 --- a/net/http/client.cpp +++ b/net/http/client.cpp @@ -113,8 +113,8 @@ class ClientImpl : public Client { CommonHeaders<> m_common_headers; ICookieJar *m_cookie_jar; ClientImpl(ICookieJar *cookie_jar, TLSContext *tls_ctx) : - m_cookie_jar(cookie_jar), - m_dialer(tls_ctx) { + m_dialer(tls_ctx), + m_cookie_jar(cookie_jar) { } using SocketStream_ptr = std::unique_ptr; diff --git a/net/http/headers.cpp b/net/http/headers.cpp index de85a649..467e1ab7 100644 --- a/net/http/headers.cpp +++ b/net/http/headers.cpp @@ -151,7 +151,10 @@ HeadersBase::KV* HeadersBase::kv_add_sort(KV kv) { if ((char*)(begin - 1) <= m_buf + m_buf_size) LOG_ERROR_RETURN(ENOBUFS, nullptr, "no buffer"); auto it = std::lower_bound(begin, kv_end(), kv, HA(this)); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" memmove(begin - 1, begin, sizeof(KV) * (it - begin)); +#pragma GCC diagnostic pop m_kv_size++; *(it - 1) = kv; return it - 1; diff --git a/net/utils.cpp b/net/utils.cpp index 3820e65a..4512733a 100644 --- a/net/utils.cpp +++ b/net/utils.cpp @@ -105,7 +105,10 @@ inline __attribute__((always_inline)) void base64_translate_3to4(const char *in, static const unsigned char tbl[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; auto v = htonl(*(uint32_t *)in); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" auto x = *(xlator *)(&v); +#pragma GCC diagnostic pop *(uint32_t *)out = ((tbl[x.a] << 24) + (tbl[x.b] << 16) + (tbl[x.c] << 8) + (tbl[x.d] << 0)); } diff --git a/thread/thread.cpp b/thread/thread.cpp index c3de95b5..473feed4 100644 --- a/thread/thread.cpp +++ b/thread/thread.cpp @@ -931,7 +931,10 @@ R"( stack_size = align_up(randomizer + stack_size + sizeof(thread), PAGE_SIZE); char* ptr = (char*)photon_thread_alloc(stack_size); auto p = ptr + stack_size - sizeof(thread) - randomizer; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wstrict-aliasing" (uint64_t&)p &= ~63; +#pragma GCC diagnostic pop auto th = new (p) thread; th->buf = ptr; th->stackful_alloc_top = ptr; From e9b62d0d2862aa5dd30ce869779fa149ff013932 Mon Sep 17 00:00:00 2001 From: Bob Chen Date: Sun, 3 Mar 2024 21:34:49 +0800 Subject: [PATCH 8/9] Fix merge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e5336aeb..a8b832d5 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,4 @@ * Made the first tag on 27 Jul 2022. Fix the compatibility for ARM CPU. Throughly compared the TCP echo server performance with other libs.

+ From a82fa352f10f3f95afaa8abe69fb607a8cd152cb Mon Sep 17 00:00:00 2001 From: Bob Chen Date: Wed, 13 Mar 2024 09:50:55 +0800 Subject: [PATCH 9/9] SNI by benwaffle - to release/0.6 (#401) * SNI * check error * remove unecessary include * fix --------- Co-authored-by: Ben Iofel --- net/http/client.cpp | 1 + net/http/test/client_tls_test.cpp | 15 +++++++++++++++ net/security-context/tls-stream.cpp | 13 +++++++++++++ net/security-context/tls-stream.h | 2 ++ 4 files changed, 31 insertions(+) diff --git a/net/http/client.cpp b/net/http/client.cpp index df349ba3..475b579c 100644 --- a/net/http/client.cpp +++ b/net/http/client.cpp @@ -73,6 +73,7 @@ ISocketStream* PooledDialer::dial(std::string_view host, uint16_t port, bool sec if (secure) { tlssock->timeout(timeout); sock = tlssock->connect(ep); + tls_stream_set_hostname(sock, strhost.c_str()); } else { tcpsock->timeout(timeout); sock = tcpsock->connect(ep); diff --git a/net/http/test/client_tls_test.cpp b/net/http/test/client_tls_test.cpp index fce96908..533489b9 100644 --- a/net/http/test/client_tls_test.cpp +++ b/net/http/test/client_tls_test.cpp @@ -78,6 +78,21 @@ TEST(client_tls, basic) { EXPECT_EQ(true, "test" == op->resp.headers["Test_Handle"]); } +// Server Name Indication (SNI) for SSL +#if OPENSSL_VERSION_NUMBER >= 0x10100000L +TEST(http_client, SNI) { + auto tls = photon::net::new_tls_context(); + DEFER(delete tls); + auto client = photon::net::http::new_http_client(nullptr, tls); + DEFER(delete client); + auto op = client->new_operation(photon::net::http::Verb::GET, "https://debug.fly.dev"); + DEFER(delete op); + op->retry = 0; + int res = op->call(); + ASSERT_EQ(0, res); +} +#endif + int main(int argc, char** arg) { if (photon::init(photon::INIT_EVENT_DEFAULT, photon::INIT_IO_NONE)) return -1; diff --git a/net/security-context/tls-stream.cpp b/net/security-context/tls-stream.cpp index dc3ffc59..b9dce05a 100644 --- a/net/security-context/tls-stream.cpp +++ b/net/security-context/tls-stream.cpp @@ -21,6 +21,7 @@ limitations under the License. #include #include #include +#include #include #include #include @@ -403,6 +404,18 @@ ISocketStream* new_tls_stream(TLSContext* ctx, ISocketStream* base, return new TLSSocketStream(ctx, base, role, ownership); }; +void tls_stream_set_hostname(ISocketStream* stream, const char* hostname) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + if (auto s1 = dynamic_cast(stream)) { + if (SSL_set_tlsext_host_name(s1->ssl, hostname) != 1) + LOG_ERROR("Failed to set hostname on tls stream: `", VALUE(hostname)); + } else if (auto s2 = dynamic_cast(stream)) { + auto underlay = static_cast(s2->get_underlay_object(0)); + tls_stream_set_hostname(underlay, hostname); + } +#endif +} + class TLSSocketClient : public ForwardSocketClient { public: TLSContext* ctx; diff --git a/net/security-context/tls-stream.h b/net/security-context/tls-stream.h index 37ccdc63..4a8d02fd 100644 --- a/net/security-context/tls-stream.h +++ b/net/security-context/tls-stream.h @@ -97,5 +97,7 @@ ISocketServer* new_tls_server(TLSContext* ctx, ISocketServer* base, ISocketClient* new_tls_client(TLSContext* ctx, ISocketClient* base, bool ownership = false); +void tls_stream_set_hostname(ISocketStream* stream, const char* hostname); + } // namespace net } // namespace photon