Add `ReadPacket` and `WritePacket` traits

dtls-srtp
Takeru Ohta 2017-03-26 03:12:29 -07:00
parent 26cb2783bc
commit 77ad3db255
7 changed files with 185 additions and 116 deletions

View File

@ -1,13 +1,14 @@
#[macro_use] #[macro_use]
extern crate trackable; extern crate trackable;
extern crate handy_async; extern crate handy_async;
extern crate crypto;
pub use error::{Error, ErrorKind}; pub use error::{Error, ErrorKind};
pub mod io; pub mod io;
pub mod packet;
pub mod traits; pub mod traits;
pub mod rfc3550; pub mod rfc3550;
pub mod rfc3711;
pub mod rfc4585; pub mod rfc4585;
pub mod rfc5761; pub mod rfc5761;

View File

@ -1,3 +0,0 @@
use io::{ReadFrom, WriteTo};
pub trait Packet: ReadFrom + WriteTo {}

View File

@ -3,8 +3,7 @@ use handy_async::sync_io::{ReadExt, WriteExt};
use {Result, ErrorKind}; use {Result, ErrorKind};
use io::{ReadFrom, WriteTo}; use io::{ReadFrom, WriteTo};
use packet::Packet; use traits::{self, Packet};
use traits;
use types::{U5, U24, RtpTimestamp, NtpTimestamp, NtpMiddleTimetamp, Ssrc, SsrcOrCsrc}; use types::{U5, U24, RtpTimestamp, NtpTimestamp, NtpMiddleTimetamp, Ssrc, SsrcOrCsrc};
use constants::RTP_VERSION; use constants::RTP_VERSION;
@ -25,16 +24,13 @@ pub const SDES_ITEM_TYPE_NOTE: u8 = 7;
pub const SDES_ITEM_TYPE_PRIV: u8 = 8; pub const SDES_ITEM_TYPE_PRIV: u8 = 8;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum RtcpPacket { pub struct RtcpPacketReader;
Sr(RtcpSenderReport), impl traits::ReadPacket for RtcpPacketReader {
Rr(RtcpReceiverReport), type Packet = RtcpPacket;
Sdes(RtcpSourceDescription), fn read_packet<R: Read>(&mut self, reader: &mut R) -> Result<Self::Packet> {
Bye(RtcpGoodbye), RtcpPacket::read_from(reader)
App(RtcpApplicationDefined), }
} fn supports_type(&self, ty: u8) -> bool {
impl Packet for RtcpPacket {}
impl traits::RtcpPacket for RtcpPacket {
fn supports_type(ty: u8) -> bool {
match ty { match ty {
RTCP_PACKET_TYPE_SR | RTCP_PACKET_TYPE_SR |
RTCP_PACKET_TYPE_RR | 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<W: Write>(&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 { impl ReadFrom for RtcpPacket {
fn read_from<R: Read>(reader: &mut R) -> Result<Self> { fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
let mut buf = [0; 2]; let mut buf = [0; 2];
@ -186,11 +202,7 @@ impl RtcpSenderReport {
} }
} }
impl Packet for RtcpSenderReport {} impl Packet for RtcpSenderReport {}
impl traits::RtcpPacket for RtcpSenderReport { impl traits::RtcpPacket for RtcpSenderReport {}
fn supports_type(ty: u8) -> bool {
ty == RTCP_PACKET_TYPE_SR
}
}
impl ReadFrom for RtcpSenderReport { impl ReadFrom for RtcpSenderReport {
fn read_from<R: Read>(reader: &mut R) -> Result<Self> { fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
let (reception_report_count, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_SR)); 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 Packet for RtcpReceiverReport {}
impl traits::RtcpPacket for RtcpReceiverReport { impl traits::RtcpPacket for RtcpReceiverReport {}
fn supports_type(ty: u8) -> bool {
ty == RTCP_PACKET_TYPE_RR
}
}
impl ReadFrom for RtcpReceiverReport { impl ReadFrom for RtcpReceiverReport {
fn read_from<R: Read>(reader: &mut R) -> Result<Self> { fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
let (reception_report_count, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_RR)); 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 Packet for RtcpSourceDescription {}
impl traits::RtcpPacket for RtcpSourceDescription { impl traits::RtcpPacket for RtcpSourceDescription {}
fn supports_type(ty: u8) -> bool {
ty == RTCP_PACKET_TYPE_SDES
}
}
impl ReadFrom for RtcpSourceDescription { impl ReadFrom for RtcpSourceDescription {
fn read_from<R: Read>(reader: &mut R) -> Result<Self> { fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
let (source_count, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_SDES)); let (source_count, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_SDES));
@ -530,11 +534,7 @@ impl RtcpGoodbye {
} }
} }
impl Packet for RtcpGoodbye {} impl Packet for RtcpGoodbye {}
impl traits::RtcpPacket for RtcpGoodbye { impl traits::RtcpPacket for RtcpGoodbye {}
fn supports_type(ty: u8) -> bool {
ty == RTCP_PACKET_TYPE_BYE
}
}
impl ReadFrom for RtcpGoodbye { impl ReadFrom for RtcpGoodbye {
fn read_from<R: Read>(reader: &mut R) -> Result<Self> { fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
let (source_count, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_BYE)); let (source_count, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_BYE));
@ -585,11 +585,7 @@ pub struct RtcpApplicationDefined {
pub data: Vec<u8>, pub data: Vec<u8>,
} }
impl Packet for RtcpApplicationDefined {} impl Packet for RtcpApplicationDefined {}
impl traits::RtcpPacket for RtcpApplicationDefined { impl traits::RtcpPacket for RtcpApplicationDefined {}
fn supports_type(ty: u8) -> bool {
ty == RTCP_PACKET_TYPE_APP
}
}
impl ReadFrom for RtcpApplicationDefined { impl ReadFrom for RtcpApplicationDefined {
fn read_from<R: Read>(reader: &mut R) -> Result<Self> { fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
let (subtype, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_APP)); let (subtype, payload) = track_try!(read_sctp(reader, RTCP_PACKET_TYPE_APP));

View File

@ -3,11 +3,31 @@ use handy_async::sync_io::{ReadExt, WriteExt};
use {Result, ErrorKind}; use {Result, ErrorKind};
use io::{ReadFrom, WriteTo}; use io::{ReadFrom, WriteTo};
use packet::Packet; use traits::{self, Packet};
use traits;
use types::{U7, RtpTimestamp, Ssrc, Csrc}; use types::{U7, RtpTimestamp, Ssrc, Csrc};
use constants::RTP_VERSION; use constants::RTP_VERSION;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RtpPacketReader;
impl traits::ReadPacket for RtpPacketReader {
type Packet = RtpPacket;
fn read_packet<R: Read>(&mut self, reader: &mut R) -> Result<Self::Packet> {
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<W: Write>(&mut self, writer: &mut W, packet: &Self::Packet) -> Result<()> {
packet.write_to(writer)
}
}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub struct RtpPacket { pub struct RtpPacket {
pub header: RtpFixedHeader, pub header: RtpFixedHeader,
@ -15,11 +35,7 @@ pub struct RtpPacket {
pub padding: Vec<u8>, pub padding: Vec<u8>,
} }
impl Packet for RtpPacket {} impl Packet for RtpPacket {}
impl traits::RtpPacket for RtpPacket { impl traits::RtpPacket for RtpPacket {}
fn supports_type(_ty: U7) -> bool {
true
}
}
impl ReadFrom for RtpPacket { impl ReadFrom for RtpPacket {
fn read_from<R: Read>(reader: &mut R) -> Result<Self> { fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
let header = track_try!(RtpFixedHeader::read_from(reader)); let header = track_try!(RtpFixedHeader::read_from(reader));

View File

@ -3,8 +3,7 @@ use handy_async::sync_io::{ReadExt, WriteExt};
use {Result, ErrorKind}; use {Result, ErrorKind};
use io::{ReadFrom, WriteTo}; use io::{ReadFrom, WriteTo};
use packet::Packet; use traits::{self, Packet};
use traits;
use types::{U5, U6, U7, U13, Ssrc}; use types::{U5, U6, U7, U13, Ssrc};
use constants::RTP_VERSION; use constants::RTP_VERSION;
use rfc3550; use rfc3550;
@ -20,18 +19,13 @@ pub const PSFB_MESSAGE_TYPE_RPSI: u8 = 3;
pub const PSFB_MESSAGE_TYPE_AFB: u8 = 15; pub const PSFB_MESSAGE_TYPE_AFB: u8 = 15;
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum RtcpPacket { pub struct RtcpPacketReader;
Sr(rfc3550::RtcpSenderReport), impl traits::ReadPacket for RtcpPacketReader {
Rr(rfc3550::RtcpReceiverReport), type Packet = RtcpPacket;
Sdes(rfc3550::RtcpSourceDescription), fn read_packet<R: Read>(&mut self, reader: &mut R) -> Result<Self::Packet> {
Bye(rfc3550::RtcpGoodbye), RtcpPacket::read_from(reader)
App(rfc3550::RtcpApplicationDefined), }
Rtpfb(RtcpTransportLayerFeedback), fn supports_type(&self, ty: u8) -> bool {
Psfb(RtcpPayloadSpecificFeedback),
}
impl Packet for RtcpPacket {}
impl traits::RtcpPacket for RtcpPacket {
fn supports_type(ty: u8) -> bool {
match ty { match ty {
rfc3550::RTCP_PACKET_TYPE_SR | rfc3550::RTCP_PACKET_TYPE_SR |
rfc3550::RTCP_PACKET_TYPE_RR | 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<W: Write>(&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 { impl ReadFrom for RtcpPacket {
fn read_from<R: Read>(reader: &mut R) -> Result<Self> { fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
let mut buf = [0; 2]; let mut buf = [0; 2];
@ -136,11 +152,7 @@ pub enum RtcpTransportLayerFeedback {
Nack(GenericNack), Nack(GenericNack),
} }
impl Packet for RtcpTransportLayerFeedback {} impl Packet for RtcpTransportLayerFeedback {}
impl traits::RtcpPacket for RtcpTransportLayerFeedback { impl traits::RtcpPacket for RtcpTransportLayerFeedback {}
fn supports_type(ty: u8) -> bool {
ty == RTCP_PACKET_TYPE_RTPFB
}
}
impl ReadFrom for RtcpTransportLayerFeedback { impl ReadFrom for RtcpTransportLayerFeedback {
fn read_from<R: Read>(reader: &mut R) -> Result<Self> { fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
let (fb_message_type, rest) = track_try!(read_common(reader, RTCP_PACKET_TYPE_RTPFB)); let (fb_message_type, rest) = track_try!(read_common(reader, RTCP_PACKET_TYPE_RTPFB));
@ -183,11 +195,7 @@ pub enum RtcpPayloadSpecificFeedback {
Afb(ApplicationLayerFeedback), Afb(ApplicationLayerFeedback),
} }
impl Packet for RtcpPayloadSpecificFeedback {} impl Packet for RtcpPayloadSpecificFeedback {}
impl traits::RtcpPacket for RtcpPayloadSpecificFeedback { impl traits::RtcpPacket for RtcpPayloadSpecificFeedback {}
fn supports_type(ty: u8) -> bool {
ty == RTCP_PACKET_TYPE_RTPFB
}
}
impl ReadFrom for RtcpPayloadSpecificFeedback { impl ReadFrom for RtcpPayloadSpecificFeedback {
fn read_from<R: Read>(reader: &mut R) -> Result<Self> { fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
let (fb_message_type, rest) = track_try!(read_common(reader, RTCP_PACKET_TYPE_PSFB)); let (fb_message_type, rest) = track_try!(read_common(reader, RTCP_PACKET_TYPE_PSFB));

View File

@ -1,9 +1,83 @@
use std::io::{Read, Write}; use std::io::{Read, Write};
use {Result, ErrorKind}; use {Result};
use io::{ReadFrom, WriteTo}; use traits::{ReadPacket, WritePacket, RtpPacket, RtcpPacket, Packet};
use traits::{RtpPacket, RtcpPacket};
use packet::Packet; #[derive(Debug, Clone, PartialEq, Eq)]
pub struct MuxPacketReader<T, U> {
rtp_reader: T,
rtcp_reader: U,
}
impl<T, U> MuxPacketReader<T, U>
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<T, U> ReadPacket for MuxPacketReader<T, U>
where T: ReadPacket,
T::Packet: RtpPacket,
U: ReadPacket,
U::Packet: RtcpPacket
{
type Packet = MuxedPacket<T::Packet, U::Packet>;
fn read_packet<R: Read>(&mut self, reader: &mut R) -> Result<Self::Packet> {
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<T, U> {
rtp_writer: T,
rtcp_writer: U,
}
impl<T, U> MuxPacketWriter<T, U>
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<T, U> WritePacket for MuxPacketWriter<T, U>
where T: WritePacket,
T::Packet: RtpPacket,
U: WritePacket,
U::Packet: RtcpPacket
{
type Packet = MuxedPacket<T::Packet, U::Packet>;
fn write_packet<W: Write>(&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)] #[derive(Debug, Clone, PartialEq, Eq)]
pub enum MuxedPacket<T, U> { pub enum MuxedPacket<T, U> {
@ -15,37 +89,3 @@ impl<T, U> Packet for MuxedPacket<T, U>
U: RtcpPacket U: RtcpPacket
{ {
} }
impl<T, U> ReadFrom for MuxedPacket<T, U>
where T: RtpPacket,
U: RtcpPacket
{
fn read_from<R: Read>(reader: &mut R) -> Result<Self> {
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<T, U> WriteTo for MuxedPacket<T, U>
where T: RtpPacket,
U: RtcpPacket
{
fn write_to<W: Write>(&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(())
}
}

View File

@ -1,9 +1,20 @@
use packet::Packet; use std::io::{Read, Write};
use types::U7;
pub trait RtpPacket: Packet { use Result;
fn supports_type(payload_type: U7) -> bool;
pub trait Packet {}
// TODO: DecodePacket(?)
pub trait ReadPacket {
type Packet: Packet;
fn read_packet<R: Read>(&mut self, reader: &mut R) -> Result<Self::Packet>;
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<W: Write>(&mut self, writer: &mut W, packet: &Self::Packet) -> Result<()>;
} }
pub trait RtpPacket: Packet {}
pub trait RtcpPacket: Packet {}