pingora_core/protocols/tls/digest.rs
1// Copyright 2026 Cloudflare, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! TLS information from the TLS connection
16
17use std::any::Any;
18use std::borrow::Cow;
19use std::sync::Arc;
20
21/// The TLS connection information
22#[derive(Clone, Debug)]
23pub struct SslDigest {
24 /// The cipher used
25 pub cipher: Cow<'static, str>,
26 /// The TLS version of this connection
27 pub version: Cow<'static, str>,
28 /// The organization of the peer's certificate
29 pub organization: Option<String>,
30 /// The serial number of the peer's certificate
31 pub serial_number: Option<String>,
32 /// The digest of the peer's certificate
33 pub cert_digest: Vec<u8>,
34 /// The user-defined TLS data
35 pub extension: SslDigestExtension,
36}
37
38impl SslDigest {
39 /// Create a new SslDigest
40 pub fn new<S>(
41 cipher: S,
42 version: S,
43 organization: Option<String>,
44 serial_number: Option<String>,
45 cert_digest: Vec<u8>,
46 ) -> Self
47 where
48 S: Into<Cow<'static, str>>,
49 {
50 SslDigest {
51 cipher: cipher.into(),
52 version: version.into(),
53 organization,
54 serial_number,
55 cert_digest,
56 extension: SslDigestExtension::default(),
57 }
58 }
59}
60
61/// The user-defined TLS data
62#[derive(Clone, Debug, Default)]
63pub struct SslDigestExtension {
64 value: Option<Arc<dyn Any + Send + Sync>>,
65}
66
67impl SslDigestExtension {
68 /// Retrieves a reference to the user-defined TLS data if it matches the specified type.
69 ///
70 /// Returns `None` if no data has been set or if the data is not of type `T`.
71 pub fn get<T>(&self) -> Option<&T>
72 where
73 T: Send + Sync + 'static,
74 {
75 self.value.as_ref().and_then(|v| v.downcast_ref::<T>())
76 }
77
78 #[allow(dead_code)]
79 pub(crate) fn set(&mut self, value: Arc<dyn Any + Send + Sync>) {
80 self.value = Some(value);
81 }
82}