Skip to content

Commit 1024ed3

Browse files
authored
Merge pull request #30 from slyoldfox/main
Consume the full stream to make sure SIP messages with bodies are fully parsed
2 parents 04c4581 + be8a1d7 commit 1024ed3

File tree

4 files changed

+99
-26
lines changed

4 files changed

+99
-26
lines changed

src/dialog/invitation.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ impl DialogLayer {
247247
};
248248
let recipient = to.uri.clone();
249249

250-
let form = rsip::typed::From {
250+
let from = rsip::typed::From {
251251
display_name: None,
252252
uri: opt.caller.clone(),
253253
params: vec![],
@@ -257,7 +257,7 @@ impl DialogLayer {
257257
let via = self.endpoint.get_via(None, None)?;
258258
let mut request =
259259
self.endpoint
260-
.make_request(rsip::Method::Invite, recipient, via, form, to, last_seq);
260+
.make_request(rsip::Method::Invite, recipient, via, from, to, last_seq);
261261

262262
let contact = rsip::typed::Contact {
263263
display_name: None,

src/dialog/registration.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ impl Registration {
358358
});
359359
}
360360

361-
let form = rsip::typed::From {
361+
let from = rsip::typed::From {
362362
display_name: None,
363363
uri: to.uri.clone(),
364364
params: vec![],
@@ -396,7 +396,7 @@ impl Registration {
396396
rsip::Method::Register,
397397
server,
398398
via,
399-
form,
399+
from,
400400
to,
401401
self.last_seq,
402402
);

src/transport/stream.rs

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -62,31 +62,37 @@ impl Decoder for SipCodec {
6262
return Ok(Some(SipCodecType::KeepaliveResponse));
6363
}
6464

65-
if let Some(end_pos) = src
66-
.windows(KEEPALIVE_REQUEST.len())
67-
.position(|window| window == KEEPALIVE_REQUEST)
68-
{
69-
let msg_end = end_pos + KEEPALIVE_REQUEST.len();
70-
let msg_data = &src[..msg_end];
71-
match SipMessage::try_from(msg_data) {
72-
Ok(msg) => {
73-
src.advance(msg_end);
74-
Ok(Some(SipCodecType::Message(msg)))
75-
}
76-
Err(e) => {
77-
src.advance(msg_end);
78-
Err(crate::Error::Error(format!(
79-
"Failed to parse SIP message: {}",
80-
e
81-
)))
65+
if let Some(headers_end) = src.windows(4).position(|w| w == b"\r\n\r\n") {
66+
let headers = &src[..headers_end + 4]; // include CRLFCRLF
67+
68+
// --- Inline get_content_length logic ---
69+
let headers_str = std::str::from_utf8(headers)
70+
.map_err(|e| crate::Error::Error(format!("Invalid UTF-8 in headers: {}", e)))?;
71+
let mut content_length = 0;
72+
for line in headers_str.lines() {
73+
if let Some(rest) = line.strip_prefix("Content-Length:") {
74+
content_length = rest
75+
.trim()
76+
.parse::<usize>()
77+
.map_err(|e| crate::Error::Error(format!("Invalid Content-Length: {}", e)))?;
78+
break;
8279
}
8380
}
84-
} else {
85-
if src.len() > MAX_SIP_MESSAGE_SIZE {
86-
return Err(crate::Error::Error("SIP message too large".to_string()));
81+
// --- End inline Content-Length logic ---
82+
83+
let total_len = headers_end + 4 + content_length;
84+
85+
if src.len() >= total_len {
86+
let msg_data = src.split_to(total_len); // consume full message
87+
let msg = SipMessage::try_from(&msg_data[..])?;
88+
return Ok(Some(SipCodecType::Message(msg)));
8789
}
88-
Ok(None)
8990
}
91+
92+
if src.len() > MAX_SIP_MESSAGE_SIZE {
93+
return Err(crate::Error::Error("SIP message too large".to_string()));
94+
}
95+
Ok(None)
9096
}
9197
}
9298

@@ -194,7 +200,8 @@ where
194200
}
195201
Err(e) => {
196202
warn!("Error decoding message from {}: {:?}", remote_addr, e);
197-
// Continue processing despite decode errors
203+
buffer.clear(); // reset buffer so we don't loop forever on bad data
204+
break; // or `return Err(e.into())` to close the connection
198205
}
199206
}
200207
}

src/transport/tests/test_stream_encoding.rs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,3 +262,69 @@ fn test_sip_codec_size_limit() {
262262
let result = codec.decode(&mut buffer);
263263
assert!(result.is_err(), "Should error on oversized message");
264264
}
265+
266+
/// Test SipCodec handling of multiple messages in one buffer (TCP packet coalescing)
267+
#[test]
268+
fn test_sip_codec_multiple_messages_with_bodies() {
269+
let mut codec = SipCodec::new();
270+
let mut buffer = BytesMut::new();
271+
272+
let message1 = "REGISTER sip:example.com SIP/2.0\r\n\
273+
Via: SIP/2.0/TCP 127.0.0.1:5060;branch=z9hG4bK-test1\r\n\
274+
From: <sip:[email protected]>;tag=test1\r\n\
275+
To: <sip:[email protected]>\r\n\
276+
Call-ID: test-call-id-1\r\n\
277+
CSeq: 1 REGISTER\r\n\
278+
Contact: <sip:[email protected]:5060>\r\n\
279+
Max-Forwards: 70\r\n\
280+
Content-Length: 11\r\n\r\nHello world";
281+
282+
let message2 = "REGISTER sip:example.com SIP/2.0\r\n\
283+
Via: SIP/2.0/TCP 127.0.0.1:5060;branch=z9hG4bK-test2\r\n\
284+
From: <sip:[email protected]>;tag=test2\r\n\
285+
To: <sip:[email protected]>\r\n\
286+
Call-ID: test-call-id-2\r\n\
287+
CSeq: 1 REGISTER\r\n\
288+
Contact: <sip:[email protected]:5060>\r\n\
289+
Max-Forwards: 70\r\n\
290+
Content-Length: 6\r\n\r\nfoobar";
291+
292+
// Add both messages to buffer
293+
buffer.extend_from_slice(message1.as_bytes());
294+
buffer.extend_from_slice(message2.as_bytes());
295+
296+
// First decode
297+
let result1 = codec
298+
.decode(&mut buffer)
299+
.expect("first decode should succeed");
300+
assert!(result1.is_some(), "Should decode first message");
301+
302+
let msg1 = result1.unwrap();
303+
match msg1 {
304+
crate::transport::stream::SipCodecType::Message(SipMessage::Request(req)) => {
305+
assert_eq!(req.call_id_header().unwrap().value(), "test-call-id-1");
306+
}
307+
_ => panic!("Expected request message"),
308+
}
309+
310+
// Second decode
311+
let result2 = codec
312+
.decode(&mut buffer)
313+
.expect("second decode should succeed");
314+
assert!(result2.is_some(), "Should decode second message");
315+
316+
let msg2 = result2.unwrap();
317+
match msg2 {
318+
crate::transport::stream::SipCodecType::Message(SipMessage::Request(req)) => {
319+
assert_eq!(req.call_id_header().unwrap().value(), "test-call-id-2");
320+
}
321+
_ => panic!("Expected request message"),
322+
}
323+
324+
// Buffer should be empty after consuming both messages
325+
assert_eq!(
326+
buffer.len(),
327+
0,
328+
"Buffer should be empty after consuming all messages"
329+
);
330+
}

0 commit comments

Comments
 (0)