1#[doc(hidden)]
2pub use tokenizer::Tokenizer;
3
4use crate::{Error, Port, Scheme};
5
6#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
8pub enum Transport {
9 Udp,
10 Tcp,
11 Tls,
12 TlsSctp,
13 Sctp,
14 Ws,
15 Wss,
16}
17
18impl Transport {
19 pub fn all() -> [Transport; 7] {
20 use Transport::*;
21
22 [Udp, Tcp, Tls, Sctp, TlsSctp, Ws, Wss]
23 }
24
25 pub fn protocols() -> [Transport; 4] {
26 use Transport::*;
27
28 [Udp, Tcp, Sctp, Ws]
29 }
30
31 pub fn secure_protocols() -> [Transport; 3] {
32 use Transport::*;
33
34 [Tcp, Sctp, Ws]
35 }
36
37 pub fn secure_transports() -> [Transport; 3] {
38 use Transport::*;
39
40 [Tls, TlsSctp, Wss]
41 }
42
43 pub fn default_secure_protocol() -> Self {
44 Transport::Tcp
45 }
46
47 pub fn default_insecure_protocol() -> Self {
48 Transport::Udp
49 }
50
51 pub fn default_secure_transport() -> Self {
52 Transport::Tls
53 }
54
55 pub fn default_insecure_transport() -> Self {
56 Transport::Udp
57 }
58
59 pub fn default_port(&self) -> Port {
60 match self {
61 Self::Udp => 5060.into(),
62 Self::Tcp => 5060.into(),
63 Self::Sctp => 5060.into(),
64 Self::TlsSctp => 5061.into(),
65 Self::Tls => 5061.into(),
66 Self::Ws => 80.into(),
67 Self::Wss => 443.into(),
68 }
69 }
70
71 pub fn protocol(&self) -> Self {
72 match self {
73 Self::Tls => Self::Tcp,
74 Self::TlsSctp => Self::Sctp,
75 Self::Wss => Self::Ws,
76 _ => *self,
77 }
78 }
79
80 pub fn is_secure(&self) -> bool {
81 Self::secure_transports().contains(self)
82 }
83
84 pub fn sip_scheme(&self) -> Scheme {
85 match self.is_secure() {
86 true => Scheme::Sips,
87 false => Scheme::Sip,
88 }
89 }
90}
91
92impl Default for Transport {
93 fn default() -> Self {
94 Self::Udp
95 }
96}
97
98impl std::fmt::Display for Transport {
99 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100 match self {
101 Self::Udp => write!(f, "UDP"),
102 Self::Tcp => write!(f, "TCP"),
103 Self::Tls => write!(f, "TLS"),
104 Self::Sctp => write!(f, "SCTP"),
105 Self::TlsSctp => write!(f, "TLS-SCTP"),
106 Self::Ws => write!(f, "WS"),
107 Self::Wss => write!(f, "WSS"),
108 }
109 }
110}
111
112impl std::str::FromStr for Transport {
113 type Err = crate::Error;
114
115 fn from_str(s: &str) -> Result<Self, Self::Err> {
116 use std::convert::TryFrom;
117
118 Self::try_from(Tokenizer::from(s))
119 }
120}
121
122impl<'a> std::convert::TryFrom<tokenizer::Tokenizer<'a, &'a str, char>> for Transport {
123 type Error = Error;
124
125 fn try_from(tokenizer: tokenizer::Tokenizer<'a, &'a str, char>) -> Result<Self, Self::Error> {
126 match tokenizer.value {
127 part if part.eq_ignore_ascii_case("UDP") => Ok(Transport::Udp),
128 part if part.eq_ignore_ascii_case("TCP") => Ok(Transport::Tcp),
129 part if part.eq_ignore_ascii_case("TLS") => Ok(Transport::Tls),
130 part if part.eq_ignore_ascii_case("SCTP") => Ok(Transport::Sctp),
131 part if part.eq_ignore_ascii_case("TLS-SCTP") => Ok(Transport::TlsSctp),
132 part if part.eq_ignore_ascii_case("WS") => Ok(Transport::Ws),
133 part if part.eq_ignore_ascii_case("WSS") => Ok(Transport::Wss),
134 part => Err(Error::ParseError(format!("unknown transport: {}", part))),
135 }
136 }
137}
138
139impl<'a> std::convert::TryFrom<tokenizer::Tokenizer<'a, &'a [u8], u8>> for Transport {
140 type Error = Error;
141
142 fn try_from(tokenizer: tokenizer::Tokenizer<'a, &'a [u8], u8>) -> Result<Self, Self::Error> {
143 use std::str::from_utf8;
144
145 let value = from_utf8(tokenizer.value)?;
146
147 Self::try_from(Tokenizer::from(value))
148 }
149}
150
151#[doc(hidden)]
152mod tokenizer {
153 use crate::{AbstractInput, AbstractInputItem, GResult, GenericNomError, TokenizerError};
154 use std::marker::PhantomData;
155
156 #[derive(Debug, PartialEq, Eq, Clone)]
157 pub struct Tokenizer<'a, T, I>
158 where
159 T: AbstractInput<'a, I>,
160 I: AbstractInputItem<I>,
161 {
162 pub value: T,
163 phantom1: PhantomData<&'a T>,
164 phantom2: PhantomData<I>,
165 }
166
167 impl<'a, T, I> From<T> for Tokenizer<'a, T, I>
168 where
169 T: AbstractInput<'a, I>,
170 I: AbstractInputItem<I>,
171 {
172 fn from(value: T) -> Self {
173 Self {
174 value,
175 phantom1: Default::default(),
176 phantom2: Default::default(),
177 }
178 }
179 }
180
181 impl<'a, T, I> Tokenizer<'a, T, I>
182 where
183 T: AbstractInput<'a, I>,
184 I: AbstractInputItem<I>,
185 {
186 pub fn tokenize(part: T) -> GResult<T, Self> {
187 use nom::{branch::alt, bytes::complete::take_until1, combinator::rest};
188
189 let (rem, transport) =
190 alt((take_until1(" "), rest))(part).map_err(|_: GenericNomError<'a, T>| {
191 TokenizerError::from(("transport", part)).into()
192 })?;
193
194 Ok((rem, Tokenizer::from(transport)))
195 }
196 }
197}
198
199#[cfg(feature = "test-utils")]
200impl testing_utils::Randomize for Transport {
201 fn random() -> Self {
202 testing_utils::sample(&Transport::protocols())
203 }
204}