Replace stream_to_be_sent with much simpler outbound_buf
We've been passing around `Stream`s of `Frame`s everywhere even though we never made use of the async nature of those (i.e. we used future::ready everywhere). This resulted in unnecessarily complicated an hard to read code. Instead we now have a simple VecDeque outbound_buf which we push packets on if we want them to be sent. No more passing around complicated return values.
This commit is contained in:
parent
499c430b47
commit
995eed0a9b
|
@ -1,10 +1,7 @@
|
||||||
use futures::future;
|
|
||||||
use futures::future::BoxFuture;
|
use futures::future::BoxFuture;
|
||||||
use futures::pin_mut;
|
use futures::pin_mut;
|
||||||
use futures::ready;
|
use futures::ready;
|
||||||
use futures::stream;
|
use futures::{Future, FutureExt, Sink, Stream};
|
||||||
use futures::stream::BoxStream;
|
|
||||||
use futures::{Future, FutureExt, Sink, Stream, StreamExt};
|
|
||||||
use libnice::ice;
|
use libnice::ice;
|
||||||
use mumble_protocol::control::msgs;
|
use mumble_protocol::control::msgs;
|
||||||
use mumble_protocol::control::ControlPacket;
|
use mumble_protocol::control::ControlPacket;
|
||||||
|
@ -25,10 +22,9 @@ use rtp::rfc3550::{
|
||||||
use rtp::rfc5761::{MuxPacketReader, MuxPacketWriter, MuxedPacket};
|
use rtp::rfc5761::{MuxPacketReader, MuxPacketWriter, MuxedPacket};
|
||||||
use rtp::rfc5764::DtlsSrtp;
|
use rtp::rfc5764::DtlsSrtp;
|
||||||
use rtp::traits::{ReadPacket, WritePacket};
|
use rtp::traits::{ReadPacket, WritePacket};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::{BTreeMap, VecDeque};
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::net::IpAddr;
|
use std::net::IpAddr;
|
||||||
use std::ops::DerefMut;
|
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::Context;
|
use std::task::Context;
|
||||||
use std::task::Poll;
|
use std::task::Poll;
|
||||||
|
@ -38,7 +34,6 @@ use tokio::time::Delay;
|
||||||
use webrtc_sdp::attribute_type::SdpAttribute;
|
use webrtc_sdp::attribute_type::SdpAttribute;
|
||||||
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::utils::EitherS;
|
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
|
|
||||||
type SessionId = u32;
|
type SessionId = u32;
|
||||||
|
@ -54,7 +49,7 @@ struct User {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl User {
|
impl User {
|
||||||
fn set_inactive(&mut self) -> impl Stream<Item = Result<Frame, Error>> {
|
fn set_inactive(&mut self) -> Option<Frame> {
|
||||||
self.timeout = None;
|
self.timeout = None;
|
||||||
|
|
||||||
if self.active {
|
if self.active {
|
||||||
|
@ -68,24 +63,24 @@ impl User {
|
||||||
|
|
||||||
let mut msg = msgs::TalkingState::new();
|
let mut msg = msgs::TalkingState::new();
|
||||||
msg.set_session(self.session);
|
msg.set_session(self.session);
|
||||||
EitherS::A(stream::once(future::ready(Ok(Frame::Client(msg.into())))))
|
Some(Frame::Client(msg.into()))
|
||||||
} else {
|
} else {
|
||||||
EitherS::B(stream::empty())
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_active(&mut self, target: u8) -> impl Stream<Item = Result<Frame, Error>> {
|
fn set_active(&mut self, target: u8) -> Option<Frame> {
|
||||||
self.timeout = Some(tokio::time::delay_for(Duration::from_millis(400)));
|
self.timeout = Some(tokio::time::delay_for(Duration::from_millis(400)));
|
||||||
|
|
||||||
if self.active {
|
if self.active {
|
||||||
EitherS::A(stream::empty())
|
None
|
||||||
} else {
|
} else {
|
||||||
self.active = true;
|
self.active = true;
|
||||||
|
|
||||||
let mut msg = msgs::TalkingState::new();
|
let mut msg = msgs::TalkingState::new();
|
||||||
msg.set_session(self.session);
|
msg.set_session(self.session);
|
||||||
msg.set_target(target.into());
|
msg.set_target(target.into());
|
||||||
EitherS::B(stream::once(future::ready(Ok(Frame::Client(msg.into())))))
|
Some(Frame::Client(msg.into()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +94,7 @@ pub struct Connection {
|
||||||
next_clientbound_frame: Option<ControlPacket<Clientbound>>,
|
next_clientbound_frame: Option<ControlPacket<Clientbound>>,
|
||||||
next_serverbound_frame: Option<ControlPacket<Serverbound>>,
|
next_serverbound_frame: Option<ControlPacket<Serverbound>>,
|
||||||
next_rtp_frame: Option<Vec<u8>>,
|
next_rtp_frame: Option<Vec<u8>>,
|
||||||
stream_to_be_sent: Option<BoxStream<'static, Result<Frame, Error>>>,
|
outbound_buf: VecDeque<Frame>,
|
||||||
|
|
||||||
ice: Option<(ice::Agent, ice::Stream)>,
|
ice: Option<(ice::Agent, ice::Stream)>,
|
||||||
candidate_gathering_done: bool,
|
candidate_gathering_done: bool,
|
||||||
|
@ -157,7 +152,7 @@ impl Connection {
|
||||||
next_clientbound_frame: None,
|
next_clientbound_frame: None,
|
||||||
next_serverbound_frame: None,
|
next_serverbound_frame: None,
|
||||||
next_rtp_frame: None,
|
next_rtp_frame: None,
|
||||||
stream_to_be_sent: None,
|
outbound_buf: VecDeque::new(),
|
||||||
ice: None,
|
ice: None,
|
||||||
candidate_gathering_done: false,
|
candidate_gathering_done: false,
|
||||||
dtls_srtp_future: None,
|
dtls_srtp_future: None,
|
||||||
|
@ -206,7 +201,7 @@ impl Connection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_ice(&mut self) -> impl Stream<Item = Result<Frame, Error>> {
|
fn setup_ice(&mut self) -> Result<(), Error> {
|
||||||
// Setup ICE agent
|
// Setup ICE agent
|
||||||
let mut agent = ice::Agent::new_rfc5245();
|
let mut agent = ice::Agent::new_rfc5245();
|
||||||
agent.set_software("mumble-web-proxy");
|
agent.set_software("mumble-web-proxy");
|
||||||
|
@ -222,11 +217,7 @@ impl Connection {
|
||||||
} {
|
} {
|
||||||
Ok(stream) => stream,
|
Ok(stream) => stream,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return stream::once(future::ready(Err(io::Error::new(
|
return Err(io::Error::new(io::ErrorKind::Other, err).into());
|
||||||
io::ErrorKind::Other,
|
|
||||||
err,
|
|
||||||
)
|
|
||||||
.into())));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let component = stream.take_components().pop().expect("one component");
|
let component = stream.take_components().pop().expect("one component");
|
||||||
|
@ -255,7 +246,8 @@ impl Connection {
|
||||||
// FIXME: verify remote fingerprint
|
// FIXME: verify remote fingerprint
|
||||||
self.dtls_srtp_future = Some(DtlsSrtp::handshake(component, acceptor).boxed());
|
self.dtls_srtp_future = Some(DtlsSrtp::handshake(component, acceptor).boxed());
|
||||||
|
|
||||||
stream::once(future::ready(Ok(Frame::Client(msg.into()))))
|
self.outbound_buf.push_back(Frame::Client(msg.into()));
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gather_ice_candidates(mut self: Pin<&mut Self>, cx: &mut Context) -> bool {
|
fn gather_ice_candidates(mut self: Pin<&mut Self>, cx: &mut Context) -> bool {
|
||||||
|
@ -287,7 +279,7 @@ impl Connection {
|
||||||
let mut msg = msgs::IceCandidate::new();
|
let mut msg = msgs::IceCandidate::new();
|
||||||
msg.set_content(format!("candidate:{}", candidate.to_string()));
|
msg.set_content(format!("candidate:{}", candidate.to_string()));
|
||||||
let frame = Frame::Client(msg.into());
|
let frame = Frame::Client(msg.into());
|
||||||
self.stream_to_be_sent = Some(Box::pin(stream::once(future::ready(Ok(frame)))));
|
self.outbound_buf.push_back(frame);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
Poll::Ready(None) => {
|
Poll::Ready(None) => {
|
||||||
|
@ -298,10 +290,7 @@ impl Connection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_voice_packet(
|
fn handle_voice_packet(&mut self, packet: VoicePacket<Clientbound>) -> Result<(), Error> {
|
||||||
&mut self,
|
|
||||||
packet: VoicePacket<Clientbound>,
|
|
||||||
) -> impl Stream<Item = Result<Frame, Error>> {
|
|
||||||
let (target, session_id, seq_num, opus_data, last_bit) = match packet {
|
let (target, session_id, seq_num, opus_data, last_bit) = match packet {
|
||||||
VoicePacket::Audio {
|
VoicePacket::Audio {
|
||||||
target,
|
target,
|
||||||
|
@ -310,7 +299,7 @@ impl Connection {
|
||||||
payload: VoicePacketPayload::Opus(data, last_bit),
|
payload: VoicePacketPayload::Opus(data, last_bit),
|
||||||
..
|
..
|
||||||
} => (target, session_id, seq_num, data, last_bit),
|
} => (target, session_id, seq_num, data, last_bit),
|
||||||
_ => return EitherS::B(stream::empty()),
|
_ => return Ok(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
// NOTE: the mumble packet id increases by 1 per 10ms of audio contained
|
// NOTE: the mumble packet id increases by 1 per 10ms of audio contained
|
||||||
|
@ -321,7 +310,7 @@ impl Connection {
|
||||||
|
|
||||||
let user = match self.sessions.get_mut(&(session_id as u32)) {
|
let user = match self.sessions.get_mut(&(session_id as u32)) {
|
||||||
Some(s) => s,
|
Some(s) => s,
|
||||||
None => return EitherS::B(stream::empty()),
|
None => return Ok(()),
|
||||||
};
|
};
|
||||||
let rtp_ssrc = user.ssrc;
|
let rtp_ssrc = user.ssrc;
|
||||||
|
|
||||||
|
@ -336,44 +325,49 @@ impl Connection {
|
||||||
let offset = seq_num - user.start_voice_seq_num;
|
let offset = seq_num - user.start_voice_seq_num;
|
||||||
let mut rtp_seq_num = user.rtp_seq_num_offset + offset as u32;
|
let mut rtp_seq_num = user.rtp_seq_num_offset + offset as u32;
|
||||||
|
|
||||||
let activity_stream = if last_bit {
|
if last_bit {
|
||||||
if seq_num <= user.highest_voice_seq_num {
|
if seq_num <= user.highest_voice_seq_num {
|
||||||
// Horribly delayed end packet from a previous stream, just drop it
|
// Horribly delayed end packet from a previous stream, just drop it
|
||||||
// (or single packet stream which would be inaudible anyway)
|
// (or single packet stream which would be inaudible anyway)
|
||||||
return EitherS::B(stream::empty());
|
return Ok(());
|
||||||
}
|
}
|
||||||
// this is the last packet of this voice transmission -> reset counters
|
// this is the last packet of this voice transmission -> reset counters
|
||||||
// doing that will effectively trash any delayed packets but that's just
|
// doing that will effectively trash any delayed packets but that's just
|
||||||
// a flaw in the mumble protocol and there's nothing we can do about it.
|
// a flaw in the mumble protocol and there's nothing we can do about it.
|
||||||
EitherS::B(user.set_inactive())
|
if let Some(frame) = user.set_inactive() {
|
||||||
|
self.outbound_buf.push_back(frame);
|
||||||
|
}
|
||||||
|
} else if seq_num == user.highest_voice_seq_num && seq_num != user.start_voice_seq_num {
|
||||||
|
// re-transmission, drop it
|
||||||
|
return Ok(());
|
||||||
|
} else if seq_num >= user.highest_voice_seq_num
|
||||||
|
&& seq_num < user.highest_voice_seq_num + 100
|
||||||
|
{
|
||||||
|
// probably same voice transmission (also not too far in the future)
|
||||||
|
user.highest_voice_seq_num = seq_num;
|
||||||
|
if let Some(frame) = user.set_active(target) {
|
||||||
|
self.outbound_buf.push_back(frame);
|
||||||
|
}
|
||||||
|
} else if seq_num < user.highest_voice_seq_num && seq_num + 100 > user.highest_voice_seq_num
|
||||||
|
{
|
||||||
|
// slightly delayed but probably same voice transmission
|
||||||
|
if let Some(frame) = user.set_active(target) {
|
||||||
|
self.outbound_buf.push_back(frame);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
EitherS::A(
|
// Either significant jitter (>2s) or we missed the end of the last
|
||||||
if seq_num == user.highest_voice_seq_num && seq_num != user.start_voice_seq_num {
|
// transmission. Since >2s jitter will break opus horribly anyway,
|
||||||
// re-transmission, drop it
|
// we assume the latter and start a new transmission
|
||||||
return EitherS::B(stream::empty());
|
if let Some(frame) = user.set_inactive() {
|
||||||
} else if seq_num >= user.highest_voice_seq_num
|
self.outbound_buf.push_back(frame);
|
||||||
&& seq_num < user.highest_voice_seq_num + 100
|
}
|
||||||
{
|
first_in_transmission = true;
|
||||||
// probably same voice transmission (also not too far in the future)
|
user.start_voice_seq_num = seq_num;
|
||||||
user.highest_voice_seq_num = seq_num;
|
user.highest_voice_seq_num = seq_num;
|
||||||
EitherS::A(user.set_active(target))
|
rtp_seq_num = user.rtp_seq_num_offset;
|
||||||
} else if seq_num < user.highest_voice_seq_num
|
if let Some(frame) = user.set_active(target) {
|
||||||
&& seq_num + 100 > user.highest_voice_seq_num
|
self.outbound_buf.push_back(frame);
|
||||||
{
|
}
|
||||||
// slightly delayed but probably same voice transmission
|
|
||||||
EitherS::A(user.set_active(target))
|
|
||||||
} else {
|
|
||||||
// Either significant jitter (>2s) or we missed the end of the last
|
|
||||||
// transmission. Since >2s jitter will break opus horribly anyway,
|
|
||||||
// we assume the latter and start a new transmission
|
|
||||||
let stream = user.set_inactive();
|
|
||||||
first_in_transmission = true;
|
|
||||||
user.start_voice_seq_num = seq_num;
|
|
||||||
user.highest_voice_seq_num = seq_num;
|
|
||||||
rtp_seq_num = user.rtp_seq_num_offset;
|
|
||||||
EitherS::B(stream.chain(user.set_active(target)))
|
|
||||||
},
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let rtp_time = 480 * rtp_seq_num;
|
let rtp_time = 480 * rtp_seq_num;
|
||||||
|
@ -393,42 +387,44 @@ impl Connection {
|
||||||
padding: Vec::new(),
|
padding: Vec::new(),
|
||||||
};
|
};
|
||||||
let frame = Frame::Rtp(MuxedPacket::Rtp(rtp));
|
let frame = Frame::Rtp(MuxedPacket::Rtp(rtp));
|
||||||
EitherS::A(activity_stream.chain(stream::once(future::ready(Ok(frame)))))
|
self.outbound_buf.push_back(frame);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_packet_from_server(
|
fn process_packet_from_server(
|
||||||
&mut self,
|
&mut self,
|
||||||
packet: ControlPacket<Clientbound>,
|
packet: ControlPacket<Clientbound>,
|
||||||
) -> impl Stream<Item = Result<Frame, Error>> {
|
) -> Result<(), Error> {
|
||||||
if !self.supports_webrtc() {
|
if !self.supports_webrtc() {
|
||||||
return EitherS::B(stream::once(future::ready(Ok(Frame::Client(packet)))));
|
self.outbound_buf.push_back(Frame::Client(packet));
|
||||||
|
return Ok(());
|
||||||
}
|
}
|
||||||
match packet {
|
match packet {
|
||||||
ControlPacket::UDPTunnel(voice) => EitherS::A(self.handle_voice_packet(*voice)),
|
ControlPacket::UDPTunnel(voice) => return self.handle_voice_packet(*voice),
|
||||||
ControlPacket::UserState(mut message) => {
|
ControlPacket::UserState(mut message) => {
|
||||||
let session_id = message.get_session();
|
let session_id = message.get_session();
|
||||||
if !self.sessions.contains_key(&session_id) {
|
if !self.sessions.contains_key(&session_id) {
|
||||||
let user = self.allocate_ssrc(session_id);
|
let user = self.allocate_ssrc(session_id);
|
||||||
message.set_ssrc(user.ssrc);
|
message.set_ssrc(user.ssrc);
|
||||||
}
|
}
|
||||||
EitherS::B(stream::once(future::ready(Ok(Frame::Client(
|
self.outbound_buf
|
||||||
(*message).into(),
|
.push_back(Frame::Client((*message).into()));
|
||||||
)))))
|
|
||||||
}
|
}
|
||||||
ControlPacket::UserRemove(message) => {
|
ControlPacket::UserRemove(message) => {
|
||||||
self.free_ssrc(message.get_session());
|
self.free_ssrc(message.get_session());
|
||||||
EitherS::B(stream::once(future::ready(Ok(Frame::Client(
|
self.outbound_buf
|
||||||
(*message).into(),
|
.push_back(Frame::Client((*message).into()));
|
||||||
)))))
|
|
||||||
}
|
}
|
||||||
other => EitherS::B(stream::once(future::ready(Ok(Frame::Client(other))))),
|
other => self.outbound_buf.push_back(Frame::Client(other)),
|
||||||
}
|
};
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_packet_from_client(
|
fn process_packet_from_client(
|
||||||
&mut self,
|
&mut self,
|
||||||
packet: ControlPacket<Serverbound>,
|
packet: ControlPacket<Serverbound>,
|
||||||
) -> Pin<Box<dyn Stream<Item = Result<Frame, Error>> + Send>> {
|
) -> Result<(), Error> {
|
||||||
match packet {
|
match packet {
|
||||||
ControlPacket::Authenticate(mut message) => {
|
ControlPacket::Authenticate(mut message) => {
|
||||||
println!("MSG Authenticate: {:?}", message);
|
println!("MSG Authenticate: {:?}", message);
|
||||||
|
@ -437,17 +433,13 @@ impl Connection {
|
||||||
message.clear_webrtc();
|
message.clear_webrtc();
|
||||||
// and make sure opus is marked as supported
|
// and make sure opus is marked as supported
|
||||||
message.set_opus(true);
|
message.set_opus(true);
|
||||||
|
self.outbound_buf
|
||||||
|
.push_back(Frame::Server((*message).into()));
|
||||||
|
|
||||||
let stream = self.setup_ice();
|
self.setup_ice()?;
|
||||||
|
|
||||||
Box::pin(
|
|
||||||
stream::once(future::ready(Ok(Frame::Server((*message).into()))))
|
|
||||||
.chain(stream),
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Box::pin(stream::once(future::ready(Ok(Frame::Server(
|
self.outbound_buf
|
||||||
(*message).into(),
|
.push_back(Frame::Server((*message).into()));
|
||||||
)))))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ControlPacket::WebRTC(mut message) => {
|
ControlPacket::WebRTC(mut message) => {
|
||||||
|
@ -462,7 +454,6 @@ impl Connection {
|
||||||
// FIXME trigger ICE-restart if required
|
// FIXME trigger ICE-restart if required
|
||||||
// FIXME store and use remote dtls fingerprint
|
// FIXME store and use remote dtls fingerprint
|
||||||
}
|
}
|
||||||
Box::pin(stream::empty())
|
|
||||||
}
|
}
|
||||||
ControlPacket::IceCandidate(mut message) => {
|
ControlPacket::IceCandidate(mut message) => {
|
||||||
let candidate = message.take_content();
|
let candidate = message.take_content();
|
||||||
|
@ -474,15 +465,14 @@ impl Connection {
|
||||||
}
|
}
|
||||||
Ok(_) => unreachable!(),
|
Ok(_) => unreachable!(),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
return Box::pin(stream::once(future::ready(Err(io::Error::new(
|
return Err(io::Error::new(
|
||||||
io::ErrorKind::Other,
|
io::ErrorKind::Other,
|
||||||
format!("Error parsing ICE candidate: {}", err),
|
format!("Error parsing ICE candidate: {}", err),
|
||||||
)
|
)
|
||||||
.into()))));
|
.into());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Box::pin(stream::empty())
|
|
||||||
}
|
}
|
||||||
ControlPacket::TalkingState(message) => {
|
ControlPacket::TalkingState(message) => {
|
||||||
self.target = if message.has_target() {
|
self.target = if message.has_target() {
|
||||||
|
@ -490,13 +480,15 @@ impl Connection {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
Box::pin(stream::empty())
|
|
||||||
}
|
}
|
||||||
other => Box::pin(stream::once(future::ready(Ok(Frame::Server(other))))),
|
other => {
|
||||||
}
|
self.outbound_buf.push_back(Frame::Server(other));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_rtp_packet(&mut self, buf: &[u8]) -> impl Stream<Item = Result<Frame, Error>> {
|
fn process_rtp_packet(&mut self, buf: &[u8]) {
|
||||||
match self.rtp_reader.read_packet(&mut &buf[..]) {
|
match self.rtp_reader.read_packet(&mut &buf[..]) {
|
||||||
Ok(MuxedPacket::Rtp(rtp)) => {
|
Ok(MuxedPacket::Rtp(rtp)) => {
|
||||||
if let Some(target) = self.target {
|
if let Some(target) = self.target {
|
||||||
|
@ -513,15 +505,12 @@ impl Connection {
|
||||||
position_info: None,
|
position_info: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
EitherS::A(stream::once(future::ready(Ok(Frame::Server(
|
self.outbound_buf
|
||||||
voice_packet.into(),
|
.push_back(Frame::Server(voice_packet.into()));
|
||||||
)))))
|
|
||||||
} else {
|
|
||||||
EitherS::B(stream::empty())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(MuxedPacket::Rtcp(_rtcp)) => EitherS::B(stream::empty()),
|
Ok(MuxedPacket::Rtcp(_rtcp)) => {}
|
||||||
Err(_err) => EitherS::B(stream::empty()), // FIXME maybe not silently drop the error?
|
Err(_err) => {} // FIXME maybe not silently drop the error?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -565,27 +554,17 @@ impl Future for Connection {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send out all pending frames
|
// Send out all pending frames
|
||||||
if self.stream_to_be_sent.is_some() {
|
if let Some(frame) = self.outbound_buf.pop_front() {
|
||||||
let mut stream = self.stream_to_be_sent.as_mut().unwrap();
|
match frame {
|
||||||
let stream = stream.deref_mut();
|
Frame::Server(frame) => self.next_serverbound_frame = Some(frame),
|
||||||
pin_mut!(stream);
|
Frame::Client(frame) => self.next_clientbound_frame = Some(frame),
|
||||||
match ready!(stream.poll_next(cx)) {
|
Frame::Rtp(frame) => {
|
||||||
Some(frame) => {
|
let mut buf = Vec::new();
|
||||||
match frame? {
|
self.rtp_writer.write_packet(&mut buf, &frame)?;
|
||||||
Frame::Server(frame) => self.next_serverbound_frame = Some(frame),
|
self.next_rtp_frame = Some(buf)
|
||||||
Frame::Client(frame) => self.next_clientbound_frame = Some(frame),
|
|
||||||
Frame::Rtp(frame) => {
|
|
||||||
let mut buf = Vec::new();
|
|
||||||
self.rtp_writer.write_packet(&mut buf, &frame)?;
|
|
||||||
self.next_rtp_frame = Some(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue 'poll;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.stream_to_be_sent = None;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
continue 'poll;
|
||||||
}
|
}
|
||||||
|
|
||||||
// All frames have been sent (or queued), flush any buffers in the output path
|
// All frames have been sent (or queued), flush any buffers in the output path
|
||||||
|
@ -607,8 +586,9 @@ impl Future for Connection {
|
||||||
if let Some(timeout) = &mut session.timeout {
|
if let Some(timeout) = &mut session.timeout {
|
||||||
pin_mut!(timeout);
|
pin_mut!(timeout);
|
||||||
if let Poll::Ready(()) = timeout.poll(cx) {
|
if let Poll::Ready(()) = timeout.poll(cx) {
|
||||||
let stream = session.set_inactive();
|
if let Some(frame) = session.set_inactive() {
|
||||||
self.stream_to_be_sent = Some(Box::pin(stream));
|
self.outbound_buf.push_back(frame);
|
||||||
|
}
|
||||||
continue 'poll;
|
continue 'poll;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -638,8 +618,7 @@ impl Future for Connection {
|
||||||
match self.inbound_server.as_mut().poll_next(cx)? {
|
match self.inbound_server.as_mut().poll_next(cx)? {
|
||||||
Poll::Pending => {}
|
Poll::Pending => {}
|
||||||
Poll::Ready(Some(frame)) => {
|
Poll::Ready(Some(frame)) => {
|
||||||
let stream = self.process_packet_from_server(frame);
|
self.process_packet_from_server(frame)?;
|
||||||
self.stream_to_be_sent = Some(Box::pin(stream));
|
|
||||||
continue 'poll;
|
continue 'poll;
|
||||||
}
|
}
|
||||||
Poll::Ready(None) => return Poll::Ready(Ok(())),
|
Poll::Ready(None) => return Poll::Ready(Ok(())),
|
||||||
|
@ -647,8 +626,7 @@ impl Future for Connection {
|
||||||
match self.inbound_client.as_mut().poll_next(cx)? {
|
match self.inbound_client.as_mut().poll_next(cx)? {
|
||||||
Poll::Pending => {}
|
Poll::Pending => {}
|
||||||
Poll::Ready(Some(frame)) => {
|
Poll::Ready(Some(frame)) => {
|
||||||
let stream = self.process_packet_from_client(frame);
|
self.process_packet_from_client(frame)?;
|
||||||
self.stream_to_be_sent = Some(stream);
|
|
||||||
continue 'poll;
|
continue 'poll;
|
||||||
}
|
}
|
||||||
Poll::Ready(None) => return Poll::Ready(Ok(())),
|
Poll::Ready(None) => return Poll::Ready(Ok(())),
|
||||||
|
@ -658,8 +636,7 @@ impl Future for Connection {
|
||||||
match dtls_srtp.poll_next(cx)? {
|
match dtls_srtp.poll_next(cx)? {
|
||||||
Poll::Pending => {}
|
Poll::Pending => {}
|
||||||
Poll::Ready(Some(frame)) => {
|
Poll::Ready(Some(frame)) => {
|
||||||
let stream = self.process_rtp_packet(&frame);
|
self.process_rtp_packet(&frame);
|
||||||
self.stream_to_be_sent = Some(Box::pin(stream));
|
|
||||||
continue 'poll;
|
continue 'poll;
|
||||||
}
|
}
|
||||||
Poll::Ready(None) => return Poll::Ready(Ok(())),
|
Poll::Ready(None) => return Poll::Ready(Ok(())),
|
||||||
|
|
|
@ -28,7 +28,6 @@ use tungstenite::protocol::WebSocketConfig;
|
||||||
|
|
||||||
mod connection;
|
mod connection;
|
||||||
mod error;
|
mod error;
|
||||||
mod utils;
|
|
||||||
use connection::Connection;
|
use connection::Connection;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
|
|
||||||
|
|
30
src/utils.rs
30
src/utils.rs
|
@ -1,30 +0,0 @@
|
||||||
use futures::pin_mut;
|
|
||||||
use futures::Stream;
|
|
||||||
use std::pin::Pin;
|
|
||||||
use std::task::{Context, Poll};
|
|
||||||
|
|
||||||
/// Like `futures::future::Either` but for Streams
|
|
||||||
pub enum EitherS<A, B> {
|
|
||||||
A(A),
|
|
||||||
B(B),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<A, B> Stream for EitherS<A, B>
|
|
||||||
where
|
|
||||||
A: Stream + Unpin,
|
|
||||||
B: Stream<Item = A::Item> + Unpin,
|
|
||||||
{
|
|
||||||
type Item = A::Item;
|
|
||||||
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
|
|
||||||
match self.get_mut() {
|
|
||||||
EitherS::A(s) => {
|
|
||||||
pin_mut!(s);
|
|
||||||
s.poll_next(cx)
|
|
||||||
}
|
|
||||||
EitherS::B(s) => {
|
|
||||||
pin_mut!(s);
|
|
||||||
s.poll_next(cx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue