@@ -472,6 +472,90 @@ impl Display for Fmtp {
472472 f. write_str ( & self . as_string ( ) )
473473 }
474474}
475+ /// RTCP port number and address to be used if not algorithmically derived
476+ /// from the RTP port described in the media line
477+ ///
478+ /// See [RFC 3605 Section 2.1] https://datatracker.ietf.org/doc/html/rfc3605#section-2.1
479+ pub struct Rtcp {
480+ /// Port used for the media stream
481+ port : u16 ,
482+ /// Network Type
483+ nettype : NetType ,
484+ /// Address type
485+ addrtype : AddrType ,
486+ /// IP Address, unicast or multicast
487+ connection_address : IpAddr ,
488+ }
489+
490+ impl Rtcp {
491+ /// Converts the Rtcp to String
492+ pub fn as_string ( & self ) -> String {
493+ format ! (
494+ "{} {} {} {}" ,
495+ self . port, self . nettype, self . addrtype, self . connection_address
496+ )
497+ }
498+ }
499+
500+ impl FromStr for Rtcp {
501+ type Err = AttributeErr ;
502+
503+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
504+ let mut i = s. split ( ' ' ) ;
505+ let Some ( port) = i. next ( ) else {
506+ return Err ( AttributeErr (
507+ "No values for rtcp attribute, failed to get port number" ,
508+ ) ) ;
509+ } ;
510+
511+ let Ok ( port) = port. parse :: < u16 > ( ) else {
512+ return Err ( AttributeErr ( "Failed to parse port in rtcp" ) ) ;
513+ } ;
514+
515+ let Some ( nettype) = i. next ( ) else {
516+ return Err ( AttributeErr (
517+ "No values for rtcp attribute, failed to get network type" ,
518+ ) ) ;
519+ } ;
520+
521+ let Ok ( nettype) = NetType :: from_str ( nettype) else {
522+ return Err ( AttributeErr ( "Failed to parse network type in rtcp" ) ) ;
523+ } ;
524+
525+ let Some ( addrtype) = i. next ( ) else {
526+ return Err ( AttributeErr (
527+ "No values for rtcp attribute, failed to get address type" ,
528+ ) ) ;
529+ } ;
530+
531+ let Ok ( addrtype) = AddrType :: from_str ( addrtype) else {
532+ return Err ( AttributeErr ( "Failed to parse address type in rtcp" ) ) ;
533+ } ;
534+
535+ let Some ( connection_addr) = i. next ( ) else {
536+ return Err ( AttributeErr (
537+ "No values for rtcp attribute, failed to get connection address" ,
538+ ) ) ;
539+ } ;
540+
541+ let Ok ( connection_address) = connection_addr. parse ( ) else {
542+ return Err ( AttributeErr ( "Failed to parse connection address in rtcp" ) ) ;
543+ } ;
544+
545+ Ok ( Self {
546+ port,
547+ nettype,
548+ addrtype,
549+ connection_address,
550+ } )
551+ }
552+ }
553+
554+ impl Display for Rtcp {
555+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
556+ f. write_str ( & self . as_string ( ) )
557+ }
558+ }
475559
476560/// Originator of the session.
477561///
@@ -998,7 +1082,15 @@ a=fingerprint:sha-256 3A:96:6D:57:B2:C2:C7:61:A0:46:3E:1C:97:39:D3:F7:0A:88:A0:B
9981082 } ,
9991083 Attribute {
10001084 attribute: "rtcp" . into( ) ,
1001- value: None ,
1085+ value: Some (
1086+ Rtcp {
1087+ port: 53020 ,
1088+ nettype: NetType :: In ,
1089+ addrtype: AddrType :: Ip4 ,
1090+ connection_address: IpAddr :: V4 ( std:: net:: Ipv4Addr :: new( 126 , 16 , 64 , 4 ) ) ,
1091+ }
1092+ . as_string( ) ,
1093+ ) ,
10021094 } ,
10031095 ] ,
10041096 } ;
@@ -1011,7 +1103,10 @@ a=fingerprint:sha-256 3A:96:6D:57:B2:C2:C7:61:A0:46:3E:1C:97:39:D3:F7:0A:88:A0:B
10111103 media. get_first_attribute_value( "rtpmap" ) ,
10121104 Ok ( Some ( "99 h263-1998/90000" ) )
10131105 ) ;
1014- assert_eq ! ( media. get_first_attribute_value( "rtcp" ) , Ok ( None ) ) ;
1106+ assert_eq ! (
1107+ media. get_first_attribute_value( "rtcp" ) ,
1108+ Ok ( Some ( "53020 IN IP4 126.16.64.4" ) )
1109+ ) ;
10151110 assert_eq ! (
10161111 media. get_first_attribute_value( "foo" ) ,
10171112 Err ( AttributeNotFoundError )
@@ -1045,13 +1140,12 @@ a=fingerprint:sha-256 3A:96:6D:57:B2:C2:C7:61:A0:46:3E:1C:97:39:D3:F7:0A:88:A0:B
10451140 ) )
10461141 ) ;
10471142
1048- assert_eq ! (
1049- media
1050- . get_attribute_values( "rtcp" )
1051- . unwrap( )
1052- . collect:: <Vec <_>>( ) ,
1053- & [ None ]
1054- ) ;
1143+ let r = media
1144+ . get_attribute_values_typed ( "rtcp" )
1145+ . collect :: < Vec < Result < Rtcp , AttributeErr > > > ( ) ;
1146+ assert_eq ! ( r[ 0 ] . as_ref( ) . unwrap( ) . addrtype, AddrType :: Ip4 ) ;
1147+ assert_eq ! ( r[ 0 ] . as_ref( ) . unwrap( ) . port, 53020 ) ;
1148+
10551149 assert ! ( media. get_attribute_values( "foo" ) . is_err( ) ) ;
10561150 }
10571151
0 commit comments