-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
detect/sip: add sticky buffers to match headers v4 #11330
Changes from all commits
f73c43d
ab8e054
8a0fa35
65236a2
b56eec5
00ef079
a16ec14
4d96d0c
025dcaa
a7923d9
9368204
5334c3f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,7 +21,7 @@ use crate::sdp::parser::{sdp_parse_message, SdpMessage}; | |
use nom7::bytes::streaming::{tag, take, take_while, take_while1}; | ||
use nom7::character::streaming::{char, crlf}; | ||
use nom7::character::{is_alphabetic, is_alphanumeric, is_digit, is_space}; | ||
use nom7::combinator::{map_res, opt}; | ||
use nom7::combinator::{map, map_res, opt}; | ||
use nom7::sequence::delimited; | ||
use nom7::{Err, IResult, Needed}; | ||
use std; | ||
|
@@ -38,7 +38,7 @@ pub struct Request { | |
pub method: String, | ||
pub path: String, | ||
pub version: String, | ||
pub headers: HashMap<String, String>, | ||
pub headers: HashMap<String, Vec<String>>, | ||
|
||
pub request_line_len: u16, | ||
pub headers_len: u16, | ||
|
@@ -52,7 +52,7 @@ pub struct Response { | |
pub version: String, | ||
pub code: String, | ||
pub reason: String, | ||
|
||
pub headers: HashMap<String, Vec<String>>, | ||
pub response_line_len: u16, | ||
pub headers_len: u16, | ||
pub body_offset: u16, | ||
|
@@ -97,6 +97,22 @@ fn is_header_value(b: u8) -> bool { | |
is_alphanumeric(b) || is_token_char(b) || b"\"#$&(),/;:<=>?@[]{}()^|~\\\t\n\r ".contains(&b) | ||
} | ||
|
||
fn expand_header_name(h: &str) -> &str { | ||
match h { | ||
"i" => "Call-ID", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we detect if some header uses the short or long form ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why should we detect that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To get the most expressivity. I guess this deserves some mention in the docs., like
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I understand what you mean. If a header uses the short form, it is 'expanded' ( converted to the long form) to enable matching in both cases with its related sticky buffer. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I meant 2 things :
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
+1 |
||
"m" => "Contact", | ||
"e" => "Content-Encoding", | ||
"l" => "Content-Length", | ||
"c" => "Content-Type", | ||
"f" => "From", | ||
"s" => "Subject", | ||
"k" => "Supported", | ||
"t" => "To", | ||
"v" => "Via", | ||
_ => h, | ||
} | ||
} | ||
|
||
pub fn sip_parse_request(oi: &[u8]) -> IResult<&[u8], Request> { | ||
let (i, method) = parse_method(oi)?; | ||
let (i, _) = char(' ')(i)?; | ||
|
@@ -135,7 +151,7 @@ pub fn sip_parse_response(oi: &[u8]) -> IResult<&[u8], Response> { | |
let (i, reason) = parse_reason(i)?; | ||
let (hi, _) = crlf(i)?; | ||
let response_line_len = oi.len() - hi.len(); | ||
let (phi, _headers) = parse_headers(hi)?; | ||
let (phi, headers) = parse_headers(hi)?; | ||
let headers_len = hi.len() - phi.len(); | ||
let (bi, _) = crlf(phi)?; | ||
let body_offset = oi.len() - bi.len(); | ||
|
@@ -146,6 +162,7 @@ pub fn sip_parse_response(oi: &[u8]) -> IResult<&[u8], Response> { | |
version, | ||
code: code.into(), | ||
reason: reason.into(), | ||
headers, | ||
|
||
response_line_len: response_line_len as u16, | ||
headers_len: headers_len as u16, | ||
|
@@ -199,7 +216,7 @@ fn hcolon(i: &[u8]) -> IResult<&[u8], char> { | |
} | ||
|
||
fn message_header(i: &[u8]) -> IResult<&[u8], Header> { | ||
let (i, n) = header_name(i)?; | ||
let (i, n) = map(header_name, expand_header_name)(i)?; | ||
let (i, _) = hcolon(i)?; | ||
let (i, v) = header_value(i)?; | ||
let (i, _) = crlf(i)?; | ||
|
@@ -217,8 +234,8 @@ pub fn sip_take_line(i: &[u8]) -> IResult<&[u8], Option<String>> { | |
Ok((i, Some(line.into()))) | ||
} | ||
|
||
pub fn parse_headers(mut input: &[u8]) -> IResult<&[u8], HashMap<String, String>> { | ||
let mut headers_map: HashMap<String, String> = HashMap::new(); | ||
pub fn parse_headers(mut input: &[u8]) -> IResult<&[u8], HashMap<String, Vec<String>>> { | ||
let mut headers_map: HashMap<String, Vec<String>> = HashMap::new(); | ||
loop { | ||
match crlf(input) as IResult<&[u8], _> { | ||
Ok((_, _)) => { | ||
|
@@ -229,7 +246,10 @@ pub fn parse_headers(mut input: &[u8]) -> IResult<&[u8], HashMap<String, String> | |
Err(Err::Incomplete(e)) => return Err(Err::Incomplete(e)), | ||
}; | ||
let (rest, header) = message_header(input)?; | ||
headers_map.insert(header.name, header.value); | ||
headers_map | ||
.entry(header.name) | ||
.or_default() | ||
.push(header.value); | ||
input = rest; | ||
} | ||
|
||
|
@@ -292,7 +312,7 @@ mod tests { | |
assert_eq!(req.method, "REGISTER"); | ||
assert_eq!(req.path, "sip:sip.cybercity.dk"); | ||
assert_eq!(req.version, "SIP/2.0"); | ||
assert_eq!(req.headers["Content-Length"], "0"); | ||
assert_eq!(req.headers["Content-Length"].first().unwrap(), "0"); | ||
} | ||
|
||
#[test] | ||
|
@@ -308,7 +328,7 @@ mod tests { | |
assert_eq!(req.method, "REGISTER"); | ||
assert_eq!(req.path, "sip:sip.cybercity.dk"); | ||
assert_eq!(req.version, "SIP/2.0"); | ||
assert_eq!(req.headers["Content-Length"], "4"); | ||
assert_eq!(req.headers["Content-Length"].first().unwrap(), "4"); | ||
assert_eq!(body, "ABCD".as_bytes()); | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: when updating copyright years, we add the current year beside the initial one: