| // Copyright 2026 The BoringSSL Authors | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // https://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| //! ALPN configuration and handling. | |
| //! | |
| //! The ALPN extension [RFC 7301] allows negotiating different application-layer | |
| //! protocols over a single port. | |
| //! This is used, for example, to negotiate HTTP/2. | |
| /// A full list of values is available in [IANA]. | |
| /// | |
| /// [RFC 7301]: <https://datatracker.ietf.org/doc/html/rfc7301> | |
| /// [IANA]: <https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids> | |
| use alloc::vec::Vec; | |
| #[derive(Default, Debug, Clone, PartialEq, Eq)] | |
| pub(crate) struct AlpnProtocols(Vec<u8>); | |
| impl AlpnProtocols { | |
| /// Append one ALPN protocol to the list. | |
| /// | |
| /// This method returns [`Err`] if `config` is empty or longer than 255 bytes, or the list | |
| /// would exceed [`u16::MAX`] bytes. | |
| pub fn append_protocol(&mut self, proto: &[u8]) -> Result<(), ()> { | |
| if proto.is_empty() { | |
| return Err(()); | |
| } | |
| let Ok(len) = u8::try_from(proto.len()) else { | |
| return Err(()); | |
| }; | |
| if self.0.len() + 1 + len as usize > u16::MAX as usize { | |
| return Err(()); | |
| } | |
| self.0.push(len); | |
| self.0.extend_from_slice(proto); | |
| Ok(()) | |
| } | |
| pub fn as_slice(&self) -> &[u8] { | |
| &self.0 | |
| } | |
| } | |
| /// HTTP/2 over TLS protocol identifier. | |
| pub const H2: &[u8] = b"h2"; | |
| /// HTTP/2 over plain TCP protocol identifier. | |
| pub const H2C: &[u8] = b"h2c"; | |
| /// HTTP/1.1 protocol identifier. | |
| pub const HTTP11: &[u8] = b"http/1.1"; | |
| /// WebRTC protocol identifier. | |
| pub const WEBRTC: &[u8] = b"webrtc"; | |
| /// Confidential WebRTC protocol identifier. | |
| pub const CONFIDENTIAL_WEBRTC: &[u8] = b"c-webrtc"; | |
| /// CoAP over TLS protocol identifier. | |
| pub const COAP: &[u8] = b"coap"; | |
| /// CoAP/DTLS protocol identifier. | |
| pub const COAP_DTLS: &[u8] = b"co"; | |
| /// HTTP/3 protocol identifier. | |
| pub const H3: &[u8] = b"h3"; | |
| /// ACME protocol identifier. | |
| pub const ACME: &[u8] = b"acme-tls/1"; | |
| /// IMAP over TLS protocol identifier. | |
| pub const IMAP: &[u8] = b"imap"; | |
| /// POP3 over TLS protocol identifier. | |
| pub const POP3: &[u8] = b"pop3"; | |
| /// FTP over TLS protocol identifier. | |
| pub const FTP: &[u8] = b"ftp"; |