1use std::io::Write;
2
3use bytes::BytesMut;
4use http::HeaderMap;
5
6use crate::Version;
7
8fn code_str(code: u16) -> Option<&'static str> {
9 match code {
10 100 => Some("Trying"),
11 180 => Some("Ringing"),
12 181 => Some("Call is Being Forwarded"),
13 182 => Some("Queued"),
14 183 => Some("Session Progress"),
15 199 => Some("Early Dialog Terminated"),
16 200 => Some("OK"),
17 202 => Some("Accepted"),
18 204 => Some("No Notification"),
19 300 => Some("Multiple Choices"),
20 301 => Some("Moved Permanently"),
21 302 => Some("Moved Temporarily"),
22 305 => Some("Use Proxy"),
23 380 => Some("Alternative Service"),
24 400 => Some("Bad Request"),
25 401 => Some("Unauthorized"),
26 402 => Some("Payment Required"),
27 403 => Some("Forbidden"),
28 404 => Some("Not Found"),
29 405 => Some("Method Not Allowed"),
30 406 => Some("Not Acceptable"),
31 407 => Some("Proxy Authentication Required"),
32 408 => Some("Request Timeout"),
33 409 => Some("Conflict"),
34 410 => Some("Gone"),
35 411 => Some("Length Required"),
36 412 => Some("Conditional Request Failed"),
37 413 => Some("Request Entity Too Large"),
38 414 => Some("Request-URI Too Long"),
39 415 => Some("Unsupported Media Type"),
40 416 => Some("Unsupported URI Scheme"),
41 417 => Some("Unknown Resource-Priority"),
42 420 => Some("Bad Extension"),
43 421 => Some("Extension Required"),
44 422 => Some("Session Interval Too Small"),
45 423 => Some("Interval Too Brief"),
46 424 => Some("Bad Location Information"),
47 428 => Some("Use Identity Header"),
48 429 => Some("Provide Referrer Identity"),
49 433 => Some("Anonymity Disallowed"),
50 436 => Some("Bad Identity-Info"),
51 437 => Some("Unsupported Certificate"),
52 438 => Some("Invalid Identity Header"),
53 439 => Some("First Hop Lacks Outbound Support"),
54 440 => Some("Max-Breadth Exceeded"),
55 469 => Some("Bad Info Package"),
56 470 => Some("Consent Needed"),
57 480 => Some("Temporarily Unavailable"),
58 481 => Some("Call/Transaction Does Not Exist"),
59 482 => Some("Loop Detected"),
60 483 => Some("Too Many Hops"),
61 484 => Some("Address Incomplete"),
62 485 => Some("Ambiguous"),
63 486 => Some("Busy Here"),
64 487 => Some("Request Terminated"),
65 488 => Some("Not Acceptable Here"),
66 489 => Some("Bad Event"),
67 491 => Some("Request Pending"),
68 493 => Some("Undecipherable"),
69 494 => Some("Security Agreement Required"),
70 500 => Some("Server Internal Error"),
71 501 => Some("Not Implemented"),
72 502 => Some("Bad Gateway"),
73 503 => Some("Service Unavailable"),
74 504 => Some("Server Time-out"),
75 505 => Some("Version Not Supported"),
76 513 => Some("Message Too Large"),
77 580 => Some("Precondition Failure"),
78 600 => Some("Busy Everywhere"),
79 603 => Some("Decline"),
80 604 => Some("Does Not Exist Anywhere"),
81 606 => Some("Not Acceptable"),
82 607 => Some("Unwanted"),
83 _ => None,
84 }
85}
86
87#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct Response {
89 pub version: Version,
90 pub code: u16,
91 pub headers: HeaderMap,
92 pub body: Vec<u8>,
93}
94
95impl Response {
96 pub fn new(code: u16) -> Self {
97 Self {
98 version: Default::default(),
99 code,
100 headers: HeaderMap::new(),
101 body: vec![],
102 }
103 }
104
105 pub fn write(&self, f: &mut impl Write) -> Result<(), std::io::Error> {
106 let code: &str = code_str(self.code).unwrap_or("");
107 write!(
108 f,
109 "SIP/{major}.{minor} {code}",
110 major = self.version.major,
111 minor = self.version.minor,
112 code = self.code,
113 )?;
114 write!(
116 f,
117 "{space}{code_string}\r\n",
118 space = if code.is_empty() { "" } else { " " },
119 code_string = code,
120 )?;
121 for (key, value) in self.headers.iter() {
122 if key == "content-length" {
123 continue;
124 }
125 write!(f, "{}: {}\r\n", key, value.to_str().unwrap())?;
126 }
127 write!(f, "content-length: {}\r\n", self.body.len())?;
128 write!(f, "\r\n")?;
129 for letter in self.body.iter() {
130 write!(f, "{}", *letter as char)?;
131 }
132 Ok(())
133 }
134
135 pub fn write_buf(&self, buf: &mut BytesMut) {
136 let mut f = buf_writer::BufWriter::new(buf);
137 self.write(&mut f).unwrap();
138 }
139}
140
141
142mod buf_writer {
153 use std::io;
154
155 use bytes::BytesMut;
156 pub struct BufWriter<'a> {
157 buf: &'a mut BytesMut,
158 }
159
160 impl<'a> BufWriter<'a> {
161 pub fn new(buf: &'a mut BytesMut) -> Self {
162 Self { buf }
163 }
164 }
165
166 impl<'a> io::Write for BufWriter<'a> {
167 fn write(&mut self, src: &[u8]) -> io::Result<usize> {
168 self.buf.extend_from_slice(src);
169 Ok(src.len())
170 }
171
172 fn flush(&mut self) -> io::Result<()> {
173 Ok(())
174 }
175 }
176}
177
178#[cfg(test)]
179mod tests {
180 use bytes::BytesMut;
181 use http::header::HeaderValue;
182
183 use super::Response;
184
185 #[test]
186 fn test() {
187 let mut res = Response::new(200);
188
189 res.headers.insert("a", HeaderValue::from_static("b"));
190 res.headers
191 .insert("content-length", HeaderValue::from_static("7"));
192 res.body = b"abcdefg".to_vec();
193 let mut buf = BytesMut::new();
194 res.write_buf(&mut buf);
195 let expected = b"SIP/2.0 200 OK\r\na: b\r\ncontent-length: 7\r\n\r\nabcdefg";
196 assert_eq!(&expected[..], buf);
197 }
198}