diff --git a/src/lib.rs b/src/lib.rs index 6ba16ea..8f8dd22 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,14 @@ #[macro_use] extern crate trackable; extern crate handy_async; +extern crate crypto; pub use error::{Error, ErrorKind}; pub mod io; -pub mod packet; pub mod traits; pub mod rfc3550; +pub mod rfc3711; pub mod rfc4585; pub mod rfc5761; diff --git a/src/packet.rs b/src/packet.rs deleted file mode 100644 index 8108cd8..0000000 --- a/src/packet.rs +++ /dev/null @@ -1,3 +0,0 @@ -use io::{ReadFrom, WriteTo}; - -pub trait Packet: ReadFrom + WriteTo {} diff --git a/src/rfc3550/rtcp.rs b/src/rfc3550/rtcp.rs index 1f591c4..a47c769 100644 --- a/src/rfc3550/rtcp.rs +++ b/src/rfc3550/rtcp.rs @@ -3,8 +3,7 @@ use handy_async::sync_io::{ReadExt, WriteExt}; use {Result, ErrorKind}; use io::{ReadFrom, WriteTo}; -use packet::Packet; -use traits; +use traits::{self, Packet}; use types::{U5, U24, RtpTimestamp, NtpTimestamp, NtpMiddleTimetamp, Ssrc, SsrcOrCsrc}; use constants::RTP_VERSION; @@ -25,16 +24,13 @@ pub const SDES_ITEM_TYPE_NOTE: u8 = 7; pub const SDES_ITEM_TYPE_PRIV: u8 = 8; #[derive(Debug, Clone, PartialEq, Eq)] -pub enum RtcpPacket { - Sr(RtcpSenderReport), - Rr(RtcpReceiverReport), - Sdes(RtcpSourceDescription), - Bye(RtcpGoodbye), - App(RtcpApplicationDefined), -} -impl Packet for RtcpPacket {} -impl traits::RtcpPacket for RtcpPacket { - fn supports_type(ty: u8) -> bool { +pub struct RtcpPacketReader; +impl traits::ReadPacket for RtcpPacketReader { + type Packet = RtcpPacket; + fn read_packet(&mut self, reader: &mut R) -> Result { + RtcpPacket::read_from(reader) + } + fn supports_type(&self, ty: u8) -> bool { match ty { RTCP_PACKET_TYPE_SR | RTCP_PACKET_TYPE_RR | @@ -45,6 +41,26 @@ impl traits::RtcpPacket for RtcpPacket { } } } + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct RtcpPacketWriter; +impl traits::WritePacket for RtcpPacketWriter { + type Packet = RtcpPacket; + fn write_packet(&mut self, writer: &mut W, packet: &Self::Packet) -> Result<()> { + packet.write_to(writer) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum RtcpPacket { + Sr(RtcpSenderReport), + Rr(RtcpReceiverReport), + Sdes(RtcpSourceDescription), + Bye(RtcpGoodbye), + App(RtcpApplicationDefined), +} +impl Packet for RtcpPacket {} +impl traits::RtcpPacket for RtcpPacket {} impl ReadFrom for RtcpPacket { fn read_from(reader: &mut R) -> Result { let mut buf = [0; 2]; @@ -186,11 +202,7 @@ impl RtcpSenderReport { } } impl Packet for RtcpSenderReport {} -impl traits::RtcpPacket for RtcpSenderReport { - fn supports_type(ty: u8) -> bool { - ty == RTCP_PACKET_TYPE_SR - } -} +impl traits::RtcpPacket for RtcpSenderReport {} impl ReadFrom for RtcpSenderReport { fn read_from(reader: &mut R) -> Result { let (reception_report_count, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_SR)); @@ -320,11 +332,7 @@ impl RtcpReceiverReport { } } impl Packet for RtcpReceiverReport {} -impl traits::RtcpPacket for RtcpReceiverReport { - fn supports_type(ty: u8) -> bool { - ty == RTCP_PACKET_TYPE_RR - } -} +impl traits::RtcpPacket for RtcpReceiverReport {} impl ReadFrom for RtcpReceiverReport { fn read_from(reader: &mut R) -> Result { let (reception_report_count, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_RR)); @@ -375,11 +383,7 @@ impl RtcpSourceDescription { } } impl Packet for RtcpSourceDescription {} -impl traits::RtcpPacket for RtcpSourceDescription { - fn supports_type(ty: u8) -> bool { - ty == RTCP_PACKET_TYPE_SDES - } -} +impl traits::RtcpPacket for RtcpSourceDescription {} impl ReadFrom for RtcpSourceDescription { fn read_from(reader: &mut R) -> Result { let (source_count, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_SDES)); @@ -530,11 +534,7 @@ impl RtcpGoodbye { } } impl Packet for RtcpGoodbye {} -impl traits::RtcpPacket for RtcpGoodbye { - fn supports_type(ty: u8) -> bool { - ty == RTCP_PACKET_TYPE_BYE - } -} +impl traits::RtcpPacket for RtcpGoodbye {} impl ReadFrom for RtcpGoodbye { fn read_from(reader: &mut R) -> Result { let (source_count, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_BYE)); @@ -585,11 +585,7 @@ pub struct RtcpApplicationDefined { pub data: Vec, } impl Packet for RtcpApplicationDefined {} -impl traits::RtcpPacket for RtcpApplicationDefined { - fn supports_type(ty: u8) -> bool { - ty == RTCP_PACKET_TYPE_APP - } -} +impl traits::RtcpPacket for RtcpApplicationDefined {} impl ReadFrom for RtcpApplicationDefined { fn read_from(reader: &mut R) -> Result { let (subtype, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_APP)); diff --git a/src/rfc3550/rtp.rs b/src/rfc3550/rtp.rs index 01c18cb..8336e4a 100644 --- a/src/rfc3550/rtp.rs +++ b/src/rfc3550/rtp.rs @@ -3,11 +3,31 @@ use handy_async::sync_io::{ReadExt, WriteExt}; use {Result, ErrorKind}; use io::{ReadFrom, WriteTo}; -use packet::Packet; -use traits; +use traits::{self, Packet}; use types::{U7, RtpTimestamp, Ssrc, Csrc}; use constants::RTP_VERSION; +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct RtpPacketReader; +impl traits::ReadPacket for RtpPacketReader { + type Packet = RtpPacket; + fn read_packet(&mut self, reader: &mut R) -> Result { + RtpPacket::read_from(reader) + } + fn supports_type(&self, _ty: u8) -> bool { + true + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct RtpPacketWriter; +impl traits::WritePacket for RtpPacketWriter { + type Packet = RtpPacket; + fn write_packet(&mut self, writer: &mut W, packet: &Self::Packet) -> Result<()> { + packet.write_to(writer) + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct RtpPacket { pub header: RtpFixedHeader, @@ -15,11 +35,7 @@ pub struct RtpPacket { pub padding: Vec, } impl Packet for RtpPacket {} -impl traits::RtpPacket for RtpPacket { - fn supports_type(_ty: U7) -> bool { - true - } -} +impl traits::RtpPacket for RtpPacket {} impl ReadFrom for RtpPacket { fn read_from(reader: &mut R) -> Result { let header = track_try!(RtpFixedHeader::read_from(reader)); diff --git a/src/rfc4585.rs b/src/rfc4585.rs index 4c9a37c..9a523f8 100644 --- a/src/rfc4585.rs +++ b/src/rfc4585.rs @@ -3,8 +3,7 @@ use handy_async::sync_io::{ReadExt, WriteExt}; use {Result, ErrorKind}; use io::{ReadFrom, WriteTo}; -use packet::Packet; -use traits; +use traits::{self, Packet}; use types::{U5, U6, U7, U13, Ssrc}; use constants::RTP_VERSION; use rfc3550; @@ -20,18 +19,13 @@ pub const PSFB_MESSAGE_TYPE_RPSI: u8 = 3; pub const PSFB_MESSAGE_TYPE_AFB: u8 = 15; #[derive(Debug, Clone, PartialEq, Eq)] -pub enum RtcpPacket { - Sr(rfc3550::RtcpSenderReport), - Rr(rfc3550::RtcpReceiverReport), - Sdes(rfc3550::RtcpSourceDescription), - Bye(rfc3550::RtcpGoodbye), - App(rfc3550::RtcpApplicationDefined), - Rtpfb(RtcpTransportLayerFeedback), - Psfb(RtcpPayloadSpecificFeedback), -} -impl Packet for RtcpPacket {} -impl traits::RtcpPacket for RtcpPacket { - fn supports_type(ty: u8) -> bool { +pub struct RtcpPacketReader; +impl traits::ReadPacket for RtcpPacketReader { + type Packet = RtcpPacket; + fn read_packet(&mut self, reader: &mut R) -> Result { + RtcpPacket::read_from(reader) + } + fn supports_type(&self, ty: u8) -> bool { match ty { rfc3550::RTCP_PACKET_TYPE_SR | rfc3550::RTCP_PACKET_TYPE_RR | @@ -44,6 +38,28 @@ impl traits::RtcpPacket for RtcpPacket { } } } + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct RtcpPacketWriter; +impl traits::WritePacket for RtcpPacketWriter { + type Packet = RtcpPacket; + fn write_packet(&mut self, writer: &mut W, packet: &Self::Packet) -> Result<()> { + packet.write_to(writer) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum RtcpPacket { + Sr(rfc3550::RtcpSenderReport), + Rr(rfc3550::RtcpReceiverReport), + Sdes(rfc3550::RtcpSourceDescription), + Bye(rfc3550::RtcpGoodbye), + App(rfc3550::RtcpApplicationDefined), + Rtpfb(RtcpTransportLayerFeedback), + Psfb(RtcpPayloadSpecificFeedback), +} +impl Packet for RtcpPacket {} +impl traits::RtcpPacket for RtcpPacket {} impl ReadFrom for RtcpPacket { fn read_from(reader: &mut R) -> Result { let mut buf = [0; 2]; @@ -136,11 +152,7 @@ pub enum RtcpTransportLayerFeedback { Nack(GenericNack), } impl Packet for RtcpTransportLayerFeedback {} -impl traits::RtcpPacket for RtcpTransportLayerFeedback { - fn supports_type(ty: u8) -> bool { - ty == RTCP_PACKET_TYPE_RTPFB - } -} +impl traits::RtcpPacket for RtcpTransportLayerFeedback {} impl ReadFrom for RtcpTransportLayerFeedback { fn read_from(reader: &mut R) -> Result { let (fb_message_type, rest) = track_try!(read_common(reader, RTCP_PACKET_TYPE_RTPFB)); @@ -183,11 +195,7 @@ pub enum RtcpPayloadSpecificFeedback { Afb(ApplicationLayerFeedback), } impl Packet for RtcpPayloadSpecificFeedback {} -impl traits::RtcpPacket for RtcpPayloadSpecificFeedback { - fn supports_type(ty: u8) -> bool { - ty == RTCP_PACKET_TYPE_RTPFB - } -} +impl traits::RtcpPacket for RtcpPayloadSpecificFeedback {} impl ReadFrom for RtcpPayloadSpecificFeedback { fn read_from(reader: &mut R) -> Result { let (fb_message_type, rest) = track_try!(read_common(reader, RTCP_PACKET_TYPE_PSFB)); diff --git a/src/rfc5761.rs b/src/rfc5761.rs index f5f639a..247bce1 100644 --- a/src/rfc5761.rs +++ b/src/rfc5761.rs @@ -1,9 +1,83 @@ use std::io::{Read, Write}; -use {Result, ErrorKind}; -use io::{ReadFrom, WriteTo}; -use traits::{RtpPacket, RtcpPacket}; -use packet::Packet; +use {Result}; +use traits::{ReadPacket, WritePacket, RtpPacket, RtcpPacket, Packet}; + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct MuxPacketReader { + rtp_reader: T, + rtcp_reader: U, +} +impl MuxPacketReader + where T: ReadPacket, + T::Packet: RtpPacket, + U: ReadPacket, + U::Packet: RtcpPacket +{ + pub fn new(rtp_reader: T, rtcp_reader: U) -> Self { + MuxPacketReader { + rtp_reader: rtp_reader, + rtcp_reader: rtcp_reader, + } + } +} +impl ReadPacket for MuxPacketReader + where T: ReadPacket, + T::Packet: RtpPacket, + U: ReadPacket, + U::Packet: RtcpPacket +{ + type Packet = MuxedPacket; + fn read_packet(&mut self, reader: &mut R) -> Result { + let mut buf = [0; 2]; + track_try!(reader.read_exact(&mut buf)); + + let ty = buf[1]; + if self.rtcp_reader.supports_type(ty) { + let reader = &mut (&buf[..]).chain(reader); + track_err!(self.rtcp_reader.read_packet(reader).map(MuxedPacket::Rtcp)) + } else { + let reader = &mut (&buf[..]).chain(reader); + track_err!(self.rtp_reader.read_packet(reader).map(MuxedPacket::Rtp)) + } + } + fn supports_type(&self, ty: u8) -> bool { + self.rtp_reader.supports_type(ty) || self.rtcp_reader.supports_type(ty) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct MuxPacketWriter { + rtp_writer: T, + rtcp_writer: U, +} +impl MuxPacketWriter + where T: WritePacket, + T::Packet: RtpPacket, + U: WritePacket, + U::Packet: RtcpPacket +{ + pub fn new(rtp_writer: T, rtcp_writer: U) -> Self { + MuxPacketWriter { + rtp_writer: rtp_writer, + rtcp_writer: rtcp_writer, + } + } +} +impl WritePacket for MuxPacketWriter + where T: WritePacket, + T::Packet: RtpPacket, + U: WritePacket, + U::Packet: RtcpPacket +{ + type Packet = MuxedPacket; + fn write_packet(&mut self, writer: &mut W, packet: &Self::Packet) -> Result<()> { + match *packet { + MuxedPacket::Rtp(ref p) => self.rtp_writer.write_packet(writer, p), + MuxedPacket::Rtcp(ref p) => self.rtcp_writer.write_packet(writer, p), + } + } +} #[derive(Debug, Clone, PartialEq, Eq)] pub enum MuxedPacket { @@ -15,37 +89,3 @@ impl Packet for MuxedPacket U: RtcpPacket { } -impl ReadFrom for MuxedPacket - where T: RtpPacket, - U: RtcpPacket -{ - fn read_from(reader: &mut R) -> Result { - let mut buf = [0; 2]; - track_try!(reader.read_exact(&mut buf)); - - let ty = buf[1]; - if U::supports_type(ty) { - let reader = &mut (&buf[..]).chain(reader); - track_err!(U::read_from(reader).map(MuxedPacket::Rtcp)) - } else if T::supports_type(ty & 0b0111_1111) { - let reader = &mut (&buf[..]).chain(reader); - track_err!(T::read_from(reader).map(MuxedPacket::Rtp)) - } else { - track_panic!(ErrorKind::Unsupported, - "Unknown packet/payload type: {}", - ty) - } - } -} -impl WriteTo for MuxedPacket - where T: RtpPacket, - U: RtcpPacket -{ - fn write_to(&self, writer: &mut W) -> Result<()> { - match *self { - MuxedPacket::Rtp(ref p) => track_try!(p.write_to(writer)), - MuxedPacket::Rtcp(ref p) => track_try!(p.write_to(writer)), - } - Ok(()) - } -} diff --git a/src/traits.rs b/src/traits.rs index ed3e2fd..3aafcdf 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,9 +1,20 @@ -use packet::Packet; -use types::U7; +use std::io::{Read, Write}; -pub trait RtpPacket: Packet { - fn supports_type(payload_type: U7) -> bool; +use Result; + +pub trait Packet {} + +// TODO: DecodePacket(?) +pub trait ReadPacket { + type Packet: Packet; + fn read_packet(&mut self, reader: &mut R) -> Result; + fn supports_type(&self, packet_type: u8) -> bool; } -pub trait RtcpPacket: Packet { - fn supports_type(packet_type: u8) -> bool; + +pub trait WritePacket { + type Packet: Packet; + fn write_packet(&mut self, writer: &mut W, packet: &Self::Packet) -> Result<()>; } + +pub trait RtpPacket: Packet {} +pub trait RtcpPacket: Packet {}