From abf10eac16eb62de76b1ae8363916e80b4deec6b Mon Sep 17 00:00:00 2001 From: Scott Lamb Date: Mon, 6 Sep 2021 12:13:26 -0700 Subject: [PATCH] use sdp-types 0.1.3 with more permissive parsing Fixes #26 Fixes #33 --- CHANGELOG.md | 3 + Cargo.lock | 19 +++--- Cargo.toml | 2 +- src/client/parse.rs | 89 +++++++++++++++------------ src/client/testdata/anpviz_sdp.txt | 21 +++++++ src/client/testdata/geovision_sdp.txt | 15 +++++ 6 files changed, 101 insertions(+), 48 deletions(-) create mode 100644 src/client/testdata/anpviz_sdp.txt create mode 100644 src/client/testdata/geovision_sdp.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ea129a..5d209ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ * warn when connecting via TCP to a known-broken live555 server version. * improve compatibility with Geovision cameras (work in progress). * UDP fixes. +* improve compatibility with cameras with non-compliant SDP, including + Anpviz ([#26](https://github.com/scottlamb/retina/issues/26) and + Geovision ([#33])(https://github.com/scottlamb/retina/issues/33)). ## `v0.3.0` (2021-08-31) diff --git a/Cargo.lock b/Cargo.lock index f1648da..09659ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -296,6 +296,12 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + [[package]] name = "form_urlencoded" version = "1.0.1" @@ -991,7 +997,7 @@ dependencies = [ "rand", "rtp-rs", "rtsp-types", - "sdp", + "sdp-types", "smallvec", "structopt", "thiserror", @@ -1061,14 +1067,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] -name = "sdp" -version = "0.1.5" +name = "sdp-types" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db73ce8329b973830407fb1ba0e51bc32716392281f7757a92f372a1420bb8ec" +checksum = "ae499f6886cff026ebd8355c8f67a1881cd15f23ce89de4aab13588cf52142dd" dependencies = [ - "rand", - "thiserror", - "url", + "bstr", + "fallible-iterator", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 1d67bde..6c2111e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ pretty-hex = "0.2.1" rand = "0.8.3" rtp-rs = "0.6.0" rtsp-types = "0.0.2" -sdp = "0.1.4" +sdp-types = "0.1.3" smallvec = { version = "1.6.1", features = ["union"] } thiserror = "1.0.25" time = "0.1.43" diff --git a/src/client/parse.rs b/src/client/parse.rs index 4082de2..cba837c 100644 --- a/src/client/parse.rs +++ b/src/client/parse.rs @@ -1,11 +1,11 @@ // Copyright (C) 2021 Scott Lamb // SPDX-License-Identifier: MIT OR Apache-2.0 -use bytes::{Buf, Bytes}; +use bytes::Bytes; use log::debug; use pretty_hex::PrettyHex; -use sdp::media_description::MediaDescription; -use std::{convert::TryFrom, net::IpAddr, num::NonZeroU16}; +use sdp_types::Media; +use std::{net::IpAddr, num::NonZeroU16}; use url::Url; use super::{Presentation, Stream}; @@ -224,21 +224,16 @@ pub(crate) fn get_cseq(response: &rtsp_types::Response) -> Option { /// Parses a [MediaDescription] to a [Stream]. /// On failure, returns an error which is expected to be supplemented with /// the [MediaDescription] debug string and packed into a `RtspResponseError`. -fn parse_media(base_url: &Url, media_description: &MediaDescription) -> Result { - let media = media_description.media_name.media.clone(); +fn parse_media(base_url: &Url, media_description: &Media) -> Result { + let media = media_description.media.clone(); // https://tools.ietf.org/html/rfc8866#section-5.14 says "If the // sub-field is "RTP/AVP" or "RTP/SAVP" the sub-fields contain RTP // payload type numbers." // https://www.iana.org/assignments/sdp-parameters/sdp-parameters.xhtml#sdp-parameters-2 - // shows several other variants, such as "TCP/RTP/AVP". Looking a "RTP" component + // shows several other variants, such as "TCP/RTP/AVP". Looking for a "RTP" component // seems appropriate. - if !media_description - .media_name - .protos - .iter() - .any(|p| p == "RTP") - { + if !media_description.proto.starts_with("RTP/") && !media_description.proto.contains("/RTP/") { return Err("Expected RTP-based proto".into()); } @@ -248,10 +243,10 @@ fn parse_media(base_url: &Url, media_description: &MediaDescription) -> Result Result Result Result