Library: Add compatibility for legacy Tokio 0.2 (#40)

Adds support to the library for tokio 0.2 backward-compatibility. This should hopefully benefit, and prevent lavalink-rs from being blocked on this feature.

These can be reached using, e.g., `gateway-tokio-02`, `driver-tokio-02`, `serenity-rustls-tokio-02`, and `serenity-native-tokio-02` features.

Naturally, this requires some jiggering about with features and the underlying CI, which has been taken care of. Twilight can't be handled in this way, as their last tokio 0.2 version uses the deprecated Discord Gateway v6.
This commit is contained in:
Kyle Simpson
2021-02-04 02:34:07 +00:00
committed by GitHub
parent b2453091e7
commit aaab97511d
24 changed files with 353 additions and 146 deletions

View File

@@ -22,7 +22,7 @@ jobs:
uses: actions-rs/clippy-check@v1 uses: actions-rs/clippy-check@v1
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}
args: --all-features args: --features full-doc
test: test:
name: Test name: Test
@@ -39,6 +39,7 @@ jobs:
- Windows - Windows
- driver only - driver only
- gateway only - gateway only
- legacy tokio
include: include:
- name: beta - name: beta
@@ -51,8 +52,13 @@ jobs:
os: windows-latest os: windows-latest
- name: driver only - name: driver only
features: driver rustls features: driver rustls
dont-test: true
- name: gateway only - name: gateway only
features: serenity-rustls features: serenity-rustls
dont-test: true
- name: legacy tokio
features: serenity-rustls-tokio-02 driver-tokio-02
dont-test: true
steps: steps:
- name: Checkout sources - name: Checkout sources
@@ -84,18 +90,18 @@ jobs:
- name: Build all features - name: Build all features
if: matrix.features == '' if: matrix.features == ''
run: cargo build --all-features run: cargo build --features full-doc
- name: Test all features - name: Test all features
if: matrix.features == '' if: matrix.features == ''
run: cargo test --all-features run: cargo test --features full-doc
- name: Build some features - name: Build some features
if: matrix.features if: matrix.features
run: cargo build --no-default-features --features "${{ matrix.features }}" run: cargo build --no-default-features --features "${{ matrix.features }}"
- name: Test some features - name: Test some features
if: matrix.features if: ${{ !matrix.dont-test && matrix.features }}
run: cargo test --no-default-features --features "${{ matrix.features }}" run: cargo test --no-default-features --features "${{ matrix.features }}"
doc: doc:
@@ -131,7 +137,7 @@ jobs:
env: env:
RUSTDOCFLAGS: -D broken_intra_doc_links RUSTDOCFLAGS: -D broken_intra_doc_links
run: | run: |
cargo doc --no-deps --all-features cargo doc --no-deps --features full-doc
examples: examples:
name: Examples name: Examples

View File

@@ -41,7 +41,7 @@ jobs:
env: env:
RUSTDOCFLAGS: -D broken_intra_doc_links RUSTDOCFLAGS: -D broken_intra_doc_links
run: | run: |
cargo doc --no-deps --features default,twilight-rustls,builtin-queue,stock-zlib cargo doc --no-deps --features full-doc
- name: Prepare docs - name: Prepare docs
shell: bash -e -O extglob {0} shell: bash -e -O extglob {0}

View File

@@ -28,6 +28,13 @@ features = ["tokio-runtime"]
optional = true optional = true
version = "0.11" version = "0.11"
[dependencies.async-tungstenite-compat]
package = "async-tungstenite"
default-features = false
features = ["tokio-runtime"]
optional = true
version = "0.9"
[dependencies.audiopus] [dependencies.audiopus]
optional = true optional = true
version = "0.2" version = "0.2"
@@ -62,7 +69,7 @@ version = "0.8"
[dependencies.serenity] [dependencies.serenity]
optional = true optional = true
version = "0.10" version = "^0.10.2"
default-features = false default-features = false
features = ["voice", "gateway"] features = ["voice", "gateway"]
@@ -83,6 +90,12 @@ optional = true
version = "1.0" version = "1.0"
default-features = false default-features = false
[dependencies.tokio-compat]
optional = true
package = "tokio"
version = "0.2"
default-features = false
[dependencies.twilight-gateway] [dependencies.twilight-gateway]
optional = true optional = true
version = "0.3" version = "0.3"
@@ -115,20 +128,35 @@ criterion = "0.3"
utils = { path = "utils" } utils = { path = "utils" }
[features] [features]
# Core features
default = [ default = [
"serenity-rustls", "serenity-rustls",
"driver", "driver",
"gateway", "gateway",
] ]
gateway = [ gateway = [
"gateway-core",
"tokio/sync",
]
gateway-core = [
"dashmap", "dashmap",
"flume", "flume",
"parking_lot", "parking_lot",
"tokio/sync",
] ]
driver = [ driver = [
"async-trait",
"async-tungstenite", "async-tungstenite",
"driver-core",
"tokio/fs",
"tokio/io-util",
"tokio/macros",
"tokio/net",
"tokio/process",
"tokio/rt",
"tokio/sync",
"tokio/time",
]
driver-core = [
"async-trait",
"audiopus", "audiopus",
"byteorder", "byteorder",
"discortp", "discortp",
@@ -138,21 +166,13 @@ driver = [
"serenity-voice-model", "serenity-voice-model",
"spin_sleep", "spin_sleep",
"streamcatcher", "streamcatcher",
"tokio/fs",
"tokio/io-util",
"tokio/macros",
"tokio/net",
"tokio/process",
"tokio/rt",
"tokio/sync",
"tokio/time",
"typemap_rev", "typemap_rev",
"url", "url",
"uuid", "uuid",
"xsalsa20poly1305", "xsalsa20poly1305",
] ]
rustls = ["async-tungstenite/tokio-rustls"] rustls = ["async-tungstenite/tokio-rustls", "rustls-marker"]
native = ["async-tungstenite/tokio-native-tls"] native = ["async-tungstenite/tokio-native-tls", "native-marker"]
serenity-rustls = ["serenity/rustls_backend", "rustls", "gateway", "serenity-deps"] serenity-rustls = ["serenity/rustls_backend", "rustls", "gateway", "serenity-deps"]
serenity-native = ["serenity/native_tls_backend", "native", "gateway", "serenity-deps"] serenity-native = ["serenity/native_tls_backend", "native", "gateway", "serenity-deps"]
twilight-rustls = ["twilight", "twilight-gateway/rustls", "rustls", "gateway"] twilight-rustls = ["twilight", "twilight-gateway/rustls", "rustls", "gateway"]
@@ -162,9 +182,41 @@ simd-zlib = ["twilight-gateway/simd-zlib"]
stock-zlib = ["twilight-gateway/stock-zlib"] stock-zlib = ["twilight-gateway/stock-zlib"]
serenity-deps = ["async-trait"] serenity-deps = ["async-trait"]
rustls-marker = []
native-marker = []
# Tokio 0.2 Compatibility features
# These should probably be dropped around the same time as serenity drop them.
rustls-tokio-02 = ["async-tungstenite-compat/tokio-rustls", "rustls-marker", "tokio-02-marker"]
native-tokio-02 = ["async-tungstenite-compat/tokio-native-tls", "native-marker", "tokio-02-marker"]
serenity-rustls-tokio-02 = ["serenity/rustls_tokio_0_2_backend", "rustls-tokio-02", "gateway-tokio-02", "serenity-deps"]
serenity-native-tokio-02 = ["serenity/native_tls_tokio_0_2_backend", "native-tokio-02", "gateway-tokio-02", "serenity-deps"]
gateway-tokio-02 = [
"gateway-core",
"tokio-02-marker",
"tokio-compat/sync",
]
driver-tokio-02 = [
"async-tungstenite-compat",
"driver-core",
"tokio-02-marker",
"tokio-compat/fs",
"tokio-compat/io-util",
"tokio-compat/macros",
"tokio-compat/net",
"tokio-compat/process",
"tokio-compat/rt-core",
"tokio-compat/sync",
"tokio-compat/time",
]
tokio-02-marker = []
# Behaviour altering features.
youtube-dlc = [] youtube-dlc = []
builtin-queue = [] builtin-queue = []
# Used for docgen/testing/benchmarking.
full-doc = ["default", "twilight-rustls", "builtin-queue", "stock-zlib"]
internals = [] internals = []
[[bench]] [[bench]]
@@ -179,4 +231,4 @@ required-features = ["internals"]
harness = false harness = false
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["default", "twilight-rustls", "builtin-queue", "stock-zlib"] features = ["full-doc"]

View File

@@ -1,4 +1,7 @@
#[cfg(all(feature = "driver", not(any(feature = "rustls", feature = "native"))))] #[cfg(all(
feature = "driver",
not(any(feature = "rustls-marker", feature = "native-marker"))
))]
compile_error!( compile_error!(
"You have the `driver` feature enabled: \ "You have the `driver` feature enabled: \
either the `rustls` or `native` feature must be either the `rustls` or `native` feature must be

View File

@@ -1,16 +1,16 @@
//! Constants affecting driver function and API handling. //! Constants affecting driver function and API handling.
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
use audiopus::{Bitrate, SampleRate}; use audiopus::{Bitrate, SampleRate};
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
use discortp::rtp::RtpType; use discortp::rtp::RtpType;
use std::time::Duration; use std::time::Duration;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
/// The voice gateway version used by the library. /// The voice gateway version used by the library.
pub const VOICE_GATEWAY_VERSION: u8 = crate::model::constants::GATEWAY_VERSION; pub const VOICE_GATEWAY_VERSION: u8 = crate::model::constants::GATEWAY_VERSION;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
/// Sample rate of audio to be sent to Discord. /// Sample rate of audio to be sent to Discord.
pub const SAMPLE_RATE: SampleRate = SampleRate::Hz48000; pub const SAMPLE_RATE: SampleRate = SampleRate::Hz48000;
@@ -23,7 +23,7 @@ pub const AUDIO_FRAME_RATE: usize = 50;
/// Length of time between any two audio frames. /// Length of time between any two audio frames.
pub const TIMESTEP_LENGTH: Duration = Duration::from_millis(1000 / AUDIO_FRAME_RATE as u64); pub const TIMESTEP_LENGTH: Duration = Duration::from_millis(1000 / AUDIO_FRAME_RATE as u64);
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
/// Default bitrate for audio. /// Default bitrate for audio.
pub const DEFAULT_BITRATE: Bitrate = Bitrate::BitsPerSecond(128_000); pub const DEFAULT_BITRATE: Bitrate = Bitrate::BitsPerSecond(128_000);
@@ -70,6 +70,6 @@ pub const SILENT_FRAME: [u8; 3] = [0xf8, 0xff, 0xfe];
/// The one (and only) RTP version. /// The one (and only) RTP version.
pub const RTP_VERSION: u8 = 2; pub const RTP_VERSION: u8 = 2;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
/// Profile type used by Discord's Opus audio traffic. /// Profile type used by Discord's Opus audio traffic.
pub const RTP_PROFILE_TYPE: RtpType = RtpType::Dynamic(120); pub const RTP_PROFILE_TYPE: RtpType = RtpType::Dynamic(120);

View File

@@ -19,15 +19,18 @@ use discortp::discord::{IpDiscoveryPacket, IpDiscoveryType, MutableIpDiscoveryPa
use error::{Error, Result}; use error::{Error, Result};
use flume::Sender; use flume::Sender;
use std::{net::IpAddr, str::FromStr, sync::Arc}; use std::{net::IpAddr, str::FromStr, sync::Arc};
use tokio::net::UdpSocket; #[cfg(not(feature = "tokio-02-marker"))]
use tokio::{net::UdpSocket, spawn};
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::{net::UdpSocket, spawn};
use tracing::{debug, info, instrument}; use tracing::{debug, info, instrument};
use url::Url; use url::Url;
use xsalsa20poly1305::{aead::NewAead, XSalsa20Poly1305 as Cipher}; use xsalsa20poly1305::{aead::NewAead, XSalsa20Poly1305 as Cipher};
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
use ws::create_rustls_client; use ws::create_rustls_client;
#[cfg(feature = "native")] #[cfg(feature = "native-marker")]
use ws::create_native_tls_client; use ws::create_native_tls_client;
pub(crate) struct Connection { pub(crate) struct Connection {
@@ -43,10 +46,10 @@ impl Connection {
) -> Result<Connection> { ) -> Result<Connection> {
let url = generate_url(&mut info.endpoint)?; let url = generate_url(&mut info.endpoint)?;
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
let mut client = create_rustls_client(url).await?; let mut client = create_rustls_client(url).await?;
#[cfg(feature = "native")] #[cfg(feature = "native-marker")]
let mut client = create_native_tls_client(url).await?; let mut client = create_native_tls_client(url).await?;
let mut hello = None; let mut hello = None;
@@ -97,7 +100,11 @@ impl Connection {
return Err(Error::CryptoModeUnavailable); return Err(Error::CryptoModeUnavailable);
} }
#[cfg(not(feature = "tokio-02-marker"))]
let udp = UdpSocket::bind("0.0.0.0:0").await?; let udp = UdpSocket::bind("0.0.0.0:0").await?;
#[cfg(feature = "tokio-02-marker")]
let mut udp = UdpSocket::bind("0.0.0.0:0").await?;
udp.connect((ready.ip, ready.port)).await?; udp.connect((ready.ip, ready.port)).await?;
// Follow Discord's IP Discovery procedures, in case NAT tunnelling is needed. // Follow Discord's IP Discovery procedures, in case NAT tunnelling is needed.
@@ -124,7 +131,7 @@ impl Connection {
} }
// We could do something clever like binary search, // We could do something clever like binary search,
// but possibility of UDP spoofing preclueds us from // but possibility of UDP spoofing precludes us from
// making the assumption we can find a "left edge" of '\0's. // making the assumption we can find a "left edge" of '\0's.
let nul_byte_index = view let nul_byte_index = view
.get_address_raw() .get_address_raw()
@@ -162,8 +169,14 @@ impl Connection {
let (udp_sender_msg_tx, udp_sender_msg_rx) = flume::unbounded(); let (udp_sender_msg_tx, udp_sender_msg_rx) = flume::unbounded();
let (udp_receiver_msg_tx, udp_receiver_msg_rx) = flume::unbounded(); let (udp_receiver_msg_tx, udp_receiver_msg_rx) = flume::unbounded();
#[cfg(not(feature = "tokio-02-marker"))]
let (udp_rx, udp_tx) = {
let udp_rx = Arc::new(udp); let udp_rx = Arc::new(udp);
let udp_tx = Arc::clone(&udp_rx); let udp_tx = Arc::clone(&udp_rx);
(udp_rx, udp_tx)
};
#[cfg(feature = "tokio-02-marker")]
let (udp_rx, udp_tx) = udp.split();
let ssrc = ready.ssrc; let ssrc = ready.ssrc;
@@ -182,7 +195,7 @@ impl Connection {
.mixer .mixer
.send(MixerMessage::SetConn(mix_conn, ready.ssrc))?; .send(MixerMessage::SetConn(mix_conn, ready.ssrc))?;
tokio::spawn(ws_task::runner( spawn(ws_task::runner(
interconnect.clone(), interconnect.clone(),
ws_msg_rx, ws_msg_rx,
client, client,
@@ -190,14 +203,14 @@ impl Connection {
hello.heartbeat_interval, hello.heartbeat_interval,
)); ));
tokio::spawn(udp_rx::runner( spawn(udp_rx::runner(
interconnect.clone(), interconnect.clone(),
udp_receiver_msg_rx, udp_receiver_msg_rx,
cipher, cipher,
config.clone(), config.clone(),
udp_rx, udp_rx,
)); ));
tokio::spawn(udp_tx::runner(udp_sender_msg_rx, ssrc, udp_tx)); spawn(udp_tx::runner(udp_sender_msg_rx, ssrc, udp_tx));
Ok(Connection { Ok(Connection {
info, info,
@@ -212,10 +225,10 @@ impl Connection {
// Thread may have died, we want to send to prompt a clean exit // Thread may have died, we want to send to prompt a clean exit
// (if at all possible) and then proceed as normal. // (if at all possible) and then proceed as normal.
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
let mut client = create_rustls_client(url).await?; let mut client = create_rustls_client(url).await?;
#[cfg(feature = "native")] #[cfg(feature = "native-marker")]
let mut client = create_native_tls_client(url).await?; let mut client = create_native_tls_client(url).await?;
client client

View File

@@ -11,6 +11,10 @@ mod ws;
pub use self::{core::*, disposal::*, events::*, mixer::*, udp_rx::*, udp_tx::*, ws::*}; pub use self::{core::*, disposal::*, events::*, mixer::*, udp_rx::*, udp_tx::*, ws::*};
use flume::Sender; use flume::Sender;
#[cfg(not(feature = "tokio-02-marker"))]
use tokio::spawn;
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::spawn;
use tracing::info; use tracing::info;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@@ -38,7 +42,7 @@ impl Interconnect {
self.events = evt_tx; self.events = evt_tx;
let ic = self.clone(); let ic = self.clone();
tokio::spawn(async move { spawn(async move {
info!("Event processor restarted."); info!("Event processor restarted.");
super::events::runner(ic, evt_rx).await; super::events::runner(ic, evt_rx).await;
info!("Event processor finished."); info!("Event processor finished.");

View File

@@ -18,7 +18,10 @@ use flume::{Receiver, Sender, TryRecvError};
use rand::random; use rand::random;
use spin_sleep::SpinSleeper; use spin_sleep::SpinSleeper;
use std::time::Instant; use std::time::Instant;
#[cfg(not(feature = "tokio-02-marker"))]
use tokio::runtime::Handle; use tokio::runtime::Handle;
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::runtime::Handle;
use tracing::{error, instrument}; use tracing::{error, instrument};
use xsalsa20poly1305::TAG_SIZE; use xsalsa20poly1305::TAG_SIZE;

View File

@@ -16,11 +16,14 @@ use super::{
use crate::events::CoreContext; use crate::events::CoreContext;
use flume::{Receiver, RecvError, Sender}; use flume::{Receiver, RecvError, Sender};
use message::*; use message::*;
use tokio::runtime::Handle; #[cfg(not(feature = "tokio-02-marker"))]
use tokio::{runtime::Handle, spawn};
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::{runtime::Handle, spawn};
use tracing::{error, info, instrument}; use tracing::{error, info, instrument};
pub(crate) fn start(config: Config, rx: Receiver<CoreMessage>, tx: Sender<CoreMessage>) { pub(crate) fn start(config: Config, rx: Receiver<CoreMessage>, tx: Sender<CoreMessage>) {
tokio::spawn(async move { spawn(async move {
info!("Driver started."); info!("Driver started.");
runner(config, rx, tx).await; runner(config, rx, tx).await;
info!("Driver finished."); info!("Driver finished.");
@@ -38,7 +41,7 @@ fn start_internals(core: Sender<CoreMessage>, config: Config) -> Interconnect {
}; };
let ic = interconnect.clone(); let ic = interconnect.clone();
tokio::spawn(async move { spawn(async move {
info!("Event processor started."); info!("Event processor started.");
events::runner(ic, evt_rx).await; events::runner(ic, evt_rx).await;
info!("Event processor finished."); info!("Event processor finished.");

View File

@@ -21,7 +21,10 @@ use discortp::{
}; };
use flume::Receiver; use flume::Receiver;
use std::{collections::HashMap, sync::Arc}; use std::{collections::HashMap, sync::Arc};
use tokio::net::UdpSocket; #[cfg(not(feature = "tokio-02-marker"))]
use tokio::{net::UdpSocket, select};
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::{net::udp::RecvHalf, select};
use tracing::{error, info, instrument, warn}; use tracing::{error, info, instrument, warn};
use xsalsa20poly1305::XSalsa20Poly1305 as Cipher; use xsalsa20poly1305::XSalsa20Poly1305 as Cipher;
@@ -236,14 +239,18 @@ struct UdpRx {
config: Config, config: Config,
packet_buffer: [u8; VOICE_PACKET_MAX], packet_buffer: [u8; VOICE_PACKET_MAX],
rx: Receiver<UdpRxMessage>, rx: Receiver<UdpRxMessage>,
#[cfg(not(feature = "tokio-02-marker"))]
udp_socket: Arc<UdpSocket>, udp_socket: Arc<UdpSocket>,
#[cfg(feature = "tokio-02-marker")]
udp_socket: RecvHalf,
} }
impl UdpRx { impl UdpRx {
#[instrument(skip(self))] #[instrument(skip(self))]
async fn run(&mut self, interconnect: &mut Interconnect) { async fn run(&mut self, interconnect: &mut Interconnect) {
loop { loop {
tokio::select! { select! {
Ok((len, _addr)) = self.udp_socket.recv_from(&mut self.packet_buffer[..]) => { Ok((len, _addr)) = self.udp_socket.recv_from(&mut self.packet_buffer[..]) => {
self.process_udp_message(interconnect, len); self.process_udp_message(interconnect, len);
} }
@@ -385,6 +392,7 @@ impl UdpRx {
} }
} }
#[cfg(not(feature = "tokio-02-marker"))]
#[instrument(skip(interconnect, rx, cipher))] #[instrument(skip(interconnect, rx, cipher))]
pub(crate) async fn runner( pub(crate) async fn runner(
mut interconnect: Interconnect, mut interconnect: Interconnect,
@@ -409,6 +417,31 @@ pub(crate) async fn runner(
info!("UDP receive handle stopped."); info!("UDP receive handle stopped.");
} }
#[cfg(feature = "tokio-02-marker")]
#[instrument(skip(interconnect, rx, cipher))]
pub(crate) async fn runner(
mut interconnect: Interconnect,
rx: Receiver<UdpRxMessage>,
cipher: Cipher,
config: Config,
udp_socket: RecvHalf,
) {
info!("UDP receive handle started.");
let mut state = UdpRx {
cipher,
decoder_map: Default::default(),
config,
packet_buffer: [0u8; VOICE_PACKET_MAX],
rx,
udp_socket,
};
state.run(&mut interconnect).await;
info!("UDP receive handle stopped.");
}
#[inline] #[inline]
fn rtp_valid(packet: RtpPacket<'_>) -> bool { fn rtp_valid(packet: RtpPacket<'_>) -> bool {
packet.get_version() == RTP_VERSION && packet.get_payload_type() == RTP_PROFILE_TYPE packet.get_version() == RTP_VERSION && packet.get_payload_type() == RTP_PROFILE_TYPE

View File

@@ -3,36 +3,50 @@ use crate::constants::*;
use discortp::discord::MutableKeepalivePacket; use discortp::discord::MutableKeepalivePacket;
use flume::Receiver; use flume::Receiver;
use std::sync::Arc; use std::sync::Arc;
#[cfg(not(feature = "tokio-02-marker"))]
use tokio::{ use tokio::{
net::UdpSocket, net::UdpSocket,
time::{timeout_at, Instant}, time::{timeout_at, Instant},
}; };
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::{
net::udp::SendHalf,
time::{timeout_at, Instant},
};
use tracing::{error, info, instrument, trace}; use tracing::{error, info, instrument, trace};
#[instrument(skip(udp_msg_rx))] struct UdpTx {
pub(crate) async fn runner(udp_msg_rx: Receiver<UdpTxMessage>, ssrc: u32, udp_tx: Arc<UdpSocket>) { ssrc: u32,
info!("UDP transmit handle started."); rx: Receiver<UdpTxMessage>,
#[cfg(not(feature = "tokio-02-marker"))]
udp_tx: Arc<UdpSocket>,
#[cfg(feature = "tokio-02-marker")]
udp_tx: SendHalf,
}
impl UdpTx {
async fn run(&mut self) {
let mut keepalive_bytes = [0u8; MutableKeepalivePacket::minimum_packet_size()]; let mut keepalive_bytes = [0u8; MutableKeepalivePacket::minimum_packet_size()];
let mut ka = MutableKeepalivePacket::new(&mut keepalive_bytes[..]) let mut ka = MutableKeepalivePacket::new(&mut keepalive_bytes[..])
.expect("FATAL: Insufficient bytes given to keepalive packet."); .expect("FATAL: Insufficient bytes given to keepalive packet.");
ka.set_ssrc(ssrc); ka.set_ssrc(self.ssrc);
let mut ka_time = Instant::now() + UDP_KEEPALIVE_GAP; let mut ka_time = Instant::now() + UDP_KEEPALIVE_GAP;
loop { loop {
use UdpTxMessage::*; use UdpTxMessage::*;
match timeout_at(ka_time, udp_msg_rx.recv_async()).await { match timeout_at(ka_time, self.rx.recv_async()).await {
Err(_) => { Err(_) => {
trace!("Sending UDP Keepalive."); trace!("Sending UDP Keepalive.");
if let Err(e) = udp_tx.send(&keepalive_bytes[..]).await { if let Err(e) = self.udp_tx.send(&keepalive_bytes[..]).await {
error!("Fatal UDP keepalive send error: {:?}.", e); error!("Fatal UDP keepalive send error: {:?}.", e);
break; break;
} }
ka_time += UDP_KEEPALIVE_GAP; ka_time += UDP_KEEPALIVE_GAP;
}, },
Ok(Ok(Packet(p))) => Ok(Ok(Packet(p))) =>
if let Err(e) = udp_tx.send(&p[..]).await { if let Err(e) = self.udp_tx.send(&p[..]).await {
error!("Fatal UDP packet send error: {:?}.", e); error!("Fatal UDP packet send error: {:?}.", e);
break; break;
}, },
@@ -45,6 +59,37 @@ pub(crate) async fn runner(udp_msg_rx: Receiver<UdpTxMessage>, ssrc: u32, udp_tx
}, },
} }
} }
}
}
#[cfg(not(feature = "tokio-02-marker"))]
#[instrument(skip(udp_msg_rx))]
pub(crate) async fn runner(udp_msg_rx: Receiver<UdpTxMessage>, ssrc: u32, udp_tx: Arc<UdpSocket>) {
info!("UDP transmit handle started.");
let mut txer = UdpTx {
ssrc,
rx: udp_msg_rx,
udp_tx,
};
txer.run().await;
info!("UDP transmit handle stopped.");
}
#[cfg(feature = "tokio-02-marker")]
#[instrument(skip(udp_msg_rx))]
pub(crate) async fn runner(udp_msg_rx: Receiver<UdpTxMessage>, ssrc: u32, udp_tx: SendHalf) {
info!("UDP transmit handle started.");
let mut txer = UdpTx {
ssrc,
rx: udp_msg_rx,
udp_tx,
};
txer.run().await;
info!("UDP transmit handle stopped."); info!("UDP transmit handle stopped.");
} }

View File

@@ -10,11 +10,23 @@ use crate::{
}, },
ws::{Error as WsError, ReceiverExt, SenderExt, WsStream}, ws::{Error as WsError, ReceiverExt, SenderExt, WsStream},
}; };
#[cfg(not(feature = "tokio-02-marker"))]
use async_tungstenite::tungstenite::protocol::frame::coding::CloseCode; use async_tungstenite::tungstenite::protocol::frame::coding::CloseCode;
#[cfg(feature = "tokio-02-marker")]
use async_tungstenite_compat::tungstenite::protocol::frame::coding::CloseCode;
use flume::Receiver; use flume::Receiver;
use rand::random; use rand::random;
use std::time::Duration; use std::time::Duration;
use tokio::time::{self, Instant}; #[cfg(not(feature = "tokio-02-marker"))]
use tokio::{
select,
time::{sleep_until, Instant},
};
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::{
select,
time::{delay_until as sleep_until, Instant},
};
use tracing::{error, info, instrument, trace, warn}; use tracing::{error, info, instrument, trace, warn};
struct AuxNetwork { struct AuxNetwork {
@@ -57,9 +69,9 @@ impl AuxNetwork {
let mut ws_error = false; let mut ws_error = false;
let mut should_reconnect = false; let mut should_reconnect = false;
let hb = time::sleep_until(next_heartbeat); let hb = sleep_until(next_heartbeat);
tokio::select! { select! {
_ = hb => { _ = hb => {
ws_error = match self.send_heartbeat().await { ws_error = match self.send_heartbeat().await {
Err(e) => { Err(e) => {

View File

@@ -4,12 +4,12 @@
use futures::channel::mpsc::TrySendError; use futures::channel::mpsc::TrySendError;
#[cfg(feature = "serenity")] #[cfg(feature = "serenity")]
use serenity::gateway::InterMessage; use serenity::gateway::InterMessage;
#[cfg(feature = "gateway")] #[cfg(feature = "gateway-core")]
use std::{error::Error, fmt}; use std::{error::Error, fmt};
#[cfg(feature = "twilight")] #[cfg(feature = "twilight")]
use twilight_gateway::shard::CommandError; use twilight_gateway::shard::CommandError;
#[cfg(feature = "gateway")] #[cfg(feature = "gateway-core")]
#[derive(Debug)] #[derive(Debug)]
/// Error returned when a manager or call handler is /// Error returned when a manager or call handler is
/// unable to send messages over Discord's gateway. /// unable to send messages over Discord's gateway.
@@ -23,7 +23,7 @@ pub enum JoinError {
/// ///
/// [`Call`]: crate::Call /// [`Call`]: crate::Call
NoCall, NoCall,
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
/// The driver failed to establish a voice connection. /// The driver failed to establish a voice connection.
Driver(ConnectionError), Driver(ConnectionError),
#[cfg(feature = "serenity")] #[cfg(feature = "serenity")]
@@ -34,7 +34,7 @@ pub enum JoinError {
Twilight(CommandError), Twilight(CommandError),
} }
#[cfg(feature = "gateway")] #[cfg(feature = "gateway-core")]
impl fmt::Display for JoinError { impl fmt::Display for JoinError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Failed to Join Voice channel: ")?; write!(f, "Failed to Join Voice channel: ")?;
@@ -42,7 +42,7 @@ impl fmt::Display for JoinError {
JoinError::Dropped => write!(f, "request was cancelled/dropped."), JoinError::Dropped => write!(f, "request was cancelled/dropped."),
JoinError::NoSender => write!(f, "no gateway destination."), JoinError::NoSender => write!(f, "no gateway destination."),
JoinError::NoCall => write!(f, "tried to leave a non-existent call."), JoinError::NoCall => write!(f, "tried to leave a non-existent call."),
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
JoinError::Driver(t) => write!(f, "internal driver error {}.", t), JoinError::Driver(t) => write!(f, "internal driver error {}.", t),
#[cfg(feature = "serenity")] #[cfg(feature = "serenity")]
JoinError::Serenity(t) => write!(f, "serenity failure {}.", t), JoinError::Serenity(t) => write!(f, "serenity failure {}.", t),
@@ -52,35 +52,35 @@ impl fmt::Display for JoinError {
} }
} }
#[cfg(feature = "gateway")] #[cfg(feature = "gateway-core")]
impl Error for JoinError {} impl Error for JoinError {}
#[cfg(all(feature = "serenity", feature = "gateway"))] #[cfg(all(feature = "serenity", feature = "gateway-core"))]
impl From<TrySendError<InterMessage>> for JoinError { impl From<TrySendError<InterMessage>> for JoinError {
fn from(e: TrySendError<InterMessage>) -> Self { fn from(e: TrySendError<InterMessage>) -> Self {
JoinError::Serenity(e) JoinError::Serenity(e)
} }
} }
#[cfg(all(feature = "twilight", feature = "gateway"))] #[cfg(all(feature = "twilight", feature = "gateway-core"))]
impl From<CommandError> for JoinError { impl From<CommandError> for JoinError {
fn from(e: CommandError) -> Self { fn from(e: CommandError) -> Self {
JoinError::Twilight(e) JoinError::Twilight(e)
} }
} }
#[cfg(all(feature = "driver", feature = "gateway"))] #[cfg(all(feature = "driver-core", feature = "gateway-core"))]
impl From<ConnectionError> for JoinError { impl From<ConnectionError> for JoinError {
fn from(e: ConnectionError) -> Self { fn from(e: ConnectionError) -> Self {
JoinError::Driver(e) JoinError::Driver(e)
} }
} }
#[cfg(feature = "gateway")] #[cfg(feature = "gateway-core")]
/// Convenience type for Discord gateway error handling. /// Convenience type for Discord gateway error handling.
pub type JoinResult<T> = Result<T, JoinError>; pub type JoinResult<T> = Result<T, JoinError>;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
pub use crate::{ pub use crate::{
driver::connection::error::{Error as ConnectionError, Result as ConnectionResult}, driver::connection::error::{Error as ConnectionError, Result as ConnectionResult},
tracks::{TrackError, TrackResult}, tracks::{TrackError, TrackResult},

View File

@@ -1,4 +1,4 @@
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
use crate::{ use crate::{
driver::{Config, Driver}, driver::{Config, Driver},
error::ConnectionResult, error::ConnectionResult,
@@ -13,13 +13,13 @@ use flume::{r#async::RecvFut, Sender};
use serde_json::json; use serde_json::json;
use tracing::instrument; use tracing::instrument;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
enum Return { enum Return {
Info(Sender<ConnectionInfo>), Info(Sender<ConnectionInfo>),
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
Conn(Sender<ConnectionResult<()>>), Conn(Sender<ConnectionResult<()>>),
} }
@@ -34,7 +34,7 @@ enum Return {
pub struct Call { pub struct Call {
connection: Option<(ChannelId, ConnectionProgress, Return)>, connection: Option<(ChannelId, ConnectionProgress, Return)>,
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
/// The internal controller of the voice connection monitor thread. /// The internal controller of the voice connection monitor thread.
driver: Driver, driver: Driver,
@@ -64,7 +64,7 @@ impl Call {
Self::new_raw(guild_id, Some(ws), user_id) Self::new_raw(guild_id, Some(ws), user_id)
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
/// Creates a new Call, configuring the driver as specified. /// Creates a new Call, configuring the driver as specified.
#[inline] #[inline]
#[instrument] #[instrument]
@@ -91,7 +91,7 @@ impl Call {
Self::new_raw(guild_id, None, user_id) Self::new_raw(guild_id, None, user_id)
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
/// Creates a new standalone Call, configuring the driver as specified. /// Creates a new standalone Call, configuring the driver as specified.
#[inline] #[inline]
#[instrument] #[instrument]
@@ -106,7 +106,7 @@ impl Call {
fn new_raw(guild_id: GuildId, ws: Option<Shard>, user_id: UserId) -> Self { fn new_raw(guild_id: GuildId, ws: Option<Shard>, user_id: UserId) -> Self {
Call { Call {
connection: None, connection: None,
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
driver: Default::default(), driver: Default::default(),
guild_id, guild_id,
self_deaf: false, self_deaf: false,
@@ -116,7 +116,7 @@ impl Call {
} }
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
fn new_raw_cfg(guild_id: GuildId, ws: Option<Shard>, user_id: UserId, config: Config) -> Self { fn new_raw_cfg(guild_id: GuildId, ws: Option<Shard>, user_id: UserId, config: Config) -> Self {
Call { Call {
connection: None, connection: None,
@@ -136,7 +136,7 @@ impl Call {
// It's okay if the receiver hung up. // It's okay if the receiver hung up.
let _ = tx.send(c.clone()); let _ = tx.send(c.clone());
}, },
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
Some((_, ConnectionProgress::Complete(c), Return::Conn(tx))) => { Some((_, ConnectionProgress::Complete(c), Return::Conn(tx))) => {
self.driver.raw_connect(c.clone(), tx.clone()); self.driver.raw_connect(c.clone(), tx.clone());
}, },
@@ -171,7 +171,7 @@ impl Call {
self.self_deaf self.self_deaf
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
/// Connect or switch to the given voice channel by its Id. /// Connect or switch to the given voice channel by its Id.
/// ///
/// This function acts as a future in two stages: /// This function acts as a future in two stages:
@@ -245,7 +245,7 @@ impl Call {
// Only send an update if we were in a voice channel. // Only send an update if we were in a voice channel.
self.connection = None; self.connection = None;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
self.driver.leave(); self.driver.leave();
self.update().await self.update().await
@@ -264,7 +264,7 @@ impl Call {
pub async fn mute(&mut self, mute: bool) -> JoinResult<()> { pub async fn mute(&mut self, mute: bool) -> JoinResult<()> {
self.self_mute = mute; self.self_mute = mute;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
self.driver.mute(mute); self.driver.mute(mute);
self.update().await self.update().await
@@ -339,7 +339,7 @@ impl Call {
} }
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
impl Deref for Call { impl Deref for Call {
type Target = Driver; type Target = Driver;
@@ -348,7 +348,7 @@ impl Deref for Call {
} }
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
impl DerefMut for Call { impl DerefMut for Call {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.driver &mut self.driver

View File

@@ -1,6 +1,6 @@
//! Newtypes around Discord IDs for library cross-compatibility. //! Newtypes around Discord IDs for library cross-compatibility.
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
use crate::model::id::{GuildId as DriverGuild, UserId as DriverUser}; use crate::model::id::{GuildId as DriverGuild, UserId as DriverUser};
#[cfg(feature = "serenity")] #[cfg(feature = "serenity")]
use serenity::model::id::{ use serenity::model::id::{
@@ -73,7 +73,7 @@ impl From<SerenityGuild> for GuildId {
} }
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
impl From<GuildId> for DriverGuild { impl From<GuildId> for DriverGuild {
fn from(id: GuildId) -> Self { fn from(id: GuildId) -> Self {
Self(id.0) Self(id.0)
@@ -106,7 +106,7 @@ impl From<SerenityUser> for UserId {
} }
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
impl From<UserId> for DriverUser { impl From<UserId> for DriverUser {
fn from(id: UserId) -> Self { fn from(id: UserId) -> Self {
Self(id.0) Self(id.0)

View File

@@ -4,7 +4,10 @@ use std::{
mem, mem,
process::Child, process::Child,
}; };
#[cfg(not(feature = "tokio-02-marker"))]
use tokio::runtime::Handle; use tokio::runtime::Handle;
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::runtime::Handle;
use tracing::debug; use tracing::debug;
/// Handle for a child process which ensures that any subprocesses are properly closed /// Handle for a child process which ensures that any subprocesses are properly closed

View File

@@ -1,7 +1,10 @@
use super::{codec::OpusDecoderState, error::DcaError, Codec, Container, Input, Metadata, Reader}; use super::{codec::OpusDecoderState, error::DcaError, Codec, Container, Input, Metadata, Reader};
use serde::Deserialize; use serde::Deserialize;
use std::{ffi::OsStr, io::BufReader, mem}; use std::{ffi::OsStr, io::BufReader, mem};
#[cfg(not(feature = "tokio-02-marker"))]
use tokio::{fs::File as TokioFile, io::AsyncReadExt}; use tokio::{fs::File as TokioFile, io::AsyncReadExt};
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::{fs::File as TokioFile, io::AsyncReadExt};
/// Creates a streamed audio source from a DCA file. /// Creates a streamed audio source from a DCA file.
/// Currently only accepts the [DCA1 format](https://github.com/bwmarrin/dca). /// Currently only accepts the [DCA1 format](https://github.com/bwmarrin/dca).

View File

@@ -11,7 +11,10 @@ use std::{
ffi::OsStr, ffi::OsStr,
process::{Command, Stdio}, process::{Command, Stdio},
}; };
#[cfg(not(feature = "tokio-02-marker"))]
use tokio::process::Command as TokioCommand; use tokio::process::Command as TokioCommand;
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::process::Command as TokioCommand;
use tracing::debug; use tracing::debug;
/// Opens an audio file through `ffmpeg` and creates an audio source. /// Opens an audio file through `ffmpeg` and creates an audio source.

View File

@@ -58,7 +58,10 @@ use audiopus::coder::GenericCtl;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use cached::OpusCompressor; use cached::OpusCompressor;
use error::{Error, Result}; use error::{Error, Result};
#[cfg(not(feature = "tokio-02-marker"))]
use tokio::runtime::Handle; use tokio::runtime::Handle;
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::runtime::Handle;
use std::{ use std::{
convert::TryFrom, convert::TryFrom,

View File

@@ -11,7 +11,10 @@ use std::{
io::{BufRead, BufReader, Read}, io::{BufRead, BufReader, Read},
process::{Command, Stdio}, process::{Command, Stdio},
}; };
#[cfg(not(feature = "tokio-02-marker"))]
use tokio::{process::Command as TokioCommand, task}; use tokio::{process::Command as TokioCommand, task};
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::{process::Command as TokioCommand, task};
use tracing::trace; use tracing::trace;
const YOUTUBE_DL_COMMAND: &str = if cfg!(feature = "youtube-dlc") { const YOUTUBE_DL_COMMAND: &str = if cfg!(feature = "youtube-dlc") {

View File

@@ -38,41 +38,41 @@
//! [lavalink]: https://github.com/Frederikam/Lavalink //! [lavalink]: https://github.com/Frederikam/Lavalink
pub mod constants; pub mod constants;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
pub mod driver; pub mod driver;
pub mod error; pub mod error;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
pub mod events; pub mod events;
#[cfg(feature = "gateway")] #[cfg(feature = "gateway-core")]
mod handler; mod handler;
pub mod id; pub mod id;
pub(crate) mod info; pub(crate) mod info;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
pub mod input; pub mod input;
#[cfg(feature = "gateway")] #[cfg(feature = "gateway-core")]
mod manager; mod manager;
#[cfg(feature = "serenity")] #[cfg(feature = "serenity")]
pub mod serenity; pub mod serenity;
#[cfg(feature = "gateway")] #[cfg(feature = "gateway-core")]
pub mod shards; pub mod shards;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
pub mod tracks; pub mod tracks;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
mod ws; mod ws;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
pub use audiopus::{self as opus, Bitrate}; pub use audiopus::{self as opus, Bitrate};
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
pub use discortp as packet; pub use discortp as packet;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
pub use serenity_voice_model as model; pub use serenity_voice_model as model;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
pub use typemap_rev as typemap; pub use typemap_rev as typemap;
#[cfg(test)] #[cfg(test)]
use utils as test_utils; use utils as test_utils;
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
pub use crate::{ pub use crate::{
driver::Driver, driver::Driver,
events::{CoreEvent, Event, EventContext, EventHandler, TrackEvent}, events::{CoreEvent, Event, EventContext, EventHandler, TrackEvent},
@@ -80,7 +80,7 @@ pub use crate::{
tracks::create_player, tracks::create_player,
}; };
#[cfg(feature = "gateway")] #[cfg(feature = "gateway-core")]
pub use crate::{handler::*, manager::*}; pub use crate::{handler::*, manager::*};
#[cfg(feature = "serenity")] #[cfg(feature = "serenity")]

View File

@@ -1,4 +1,4 @@
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
use crate::driver::Config; use crate::driver::Config;
use crate::{ use crate::{
error::{JoinError, JoinResult}, error::{JoinError, JoinResult},
@@ -23,7 +23,10 @@ use serenity::{
}, },
}; };
use std::sync::Arc; use std::sync::Arc;
#[cfg(not(feature = "tokio-02-marker"))]
use tokio::sync::Mutex; use tokio::sync::Mutex;
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::sync::Mutex;
#[cfg(feature = "twilight")] #[cfg(feature = "twilight")]
use twilight_gateway::Cluster; use twilight_gateway::Cluster;
#[cfg(feature = "twilight")] #[cfg(feature = "twilight")]
@@ -48,7 +51,7 @@ pub struct Songbird {
calls: DashMap<GuildId, Arc<Mutex<Call>>>, calls: DashMap<GuildId, Arc<Mutex<Call>>>,
sharder: Sharder, sharder: Sharder,
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
driver_config: PRwLock<Option<Config>>, driver_config: PRwLock<Option<Config>>,
} }
@@ -65,7 +68,7 @@ impl Songbird {
calls: Default::default(), calls: Default::default(),
sharder: Sharder::Serenity(Default::default()), sharder: Sharder::Serenity(Default::default()),
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
driver_config: Default::default(), driver_config: Default::default(),
}) })
} }
@@ -91,7 +94,7 @@ impl Songbird {
calls: Default::default(), calls: Default::default(),
sharder: Sharder::Twilight(cluster), sharder: Sharder::Twilight(cluster),
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
driver_config: Default::default(), driver_config: Default::default(),
}) })
} }
@@ -141,7 +144,7 @@ impl Songbird {
.get_shard(shard) .get_shard(shard)
.expect("Failed to get shard handle: shard_count incorrect?"); .expect("Failed to get shard handle: shard_count incorrect?");
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
let call = Call::from_driver_config( let call = Call::from_driver_config(
guild_id, guild_id,
shard_handle, shard_handle,
@@ -149,7 +152,7 @@ impl Songbird {
self.driver_config.read().clone().unwrap_or_default(), self.driver_config.read().clone().unwrap_or_default(),
); );
#[cfg(not(feature = "driver"))] #[cfg(not(feature = "driver-core"))]
let call = Call::new(guild_id, shard_handle, info.user_id); let call = Call::new(guild_id, shard_handle, info.user_id);
Arc::new(Mutex::new(call)) Arc::new(Mutex::new(call))
@@ -164,7 +167,7 @@ impl Songbird {
*client_data *client_data
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
/// Connects to a target by retrieving its relevant [`Call`] and /// Connects to a target by retrieving its relevant [`Call`] and
/// connecting, or creating the handler if required. /// connecting, or creating the handler if required.
/// ///
@@ -196,7 +199,7 @@ impl Songbird {
self._join(guild_id.into(), channel_id.into()).await self._join(guild_id.into(), channel_id.into()).await
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
async fn _join( async fn _join(
&self, &self,
guild_id: GuildId, guild_id: GuildId,
@@ -388,7 +391,7 @@ impl VoiceGatewayManager for Songbird {
} }
} }
#[cfg(feature = "driver")] #[cfg(feature = "driver-core")]
impl Songbird { impl Songbird {
/// Sets a shared configuration for all drivers created from this /// Sets a shared configuration for all drivers created from this
/// manager. /// manager.

View File

@@ -5,7 +5,10 @@ use crate::{
}; };
use flume::Sender; use flume::Sender;
use std::{fmt, sync::Arc, time::Duration}; use std::{fmt, sync::Arc, time::Duration};
#[cfg(not(feature = "tokio-02-marker"))]
use tokio::sync::RwLock; use tokio::sync::RwLock;
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::sync::RwLock;
use typemap_rev::TypeMap; use typemap_rev::TypeMap;
use uuid::Uuid; use uuid::Uuid;

View File

@@ -6,14 +6,26 @@
use crate::model::Event; use crate::model::Event;
use async_trait::async_trait; use async_trait::async_trait;
#[cfg(not(feature = "tokio-02-marker"))]
use async_tungstenite::{ use async_tungstenite::{
self as tungstenite,
tokio::ConnectStream,
tungstenite::{error::Error as TungsteniteError, protocol::CloseFrame, Message},
WebSocketStream,
};
#[cfg(feature = "tokio-02-marker")]
use async_tungstenite_compat::{
self as tungstenite,
tokio::ConnectStream, tokio::ConnectStream,
tungstenite::{error::Error as TungsteniteError, protocol::CloseFrame, Message}, tungstenite::{error::Error as TungsteniteError, protocol::CloseFrame, Message},
WebSocketStream, WebSocketStream,
}; };
use futures::{SinkExt, StreamExt, TryStreamExt}; use futures::{SinkExt, StreamExt, TryStreamExt};
use serde_json::Error as JsonError; use serde_json::Error as JsonError;
use tokio::time::timeout; #[cfg(not(feature = "tokio-02-marker"))]
use tokio::time::{timeout, Duration};
#[cfg(feature = "tokio-02-marker")]
use tokio_compat::time::{timeout, Duration};
use tracing::{instrument, warn}; use tracing::{instrument, warn};
pub type WsStream = WebSocketStream<ConnectStream>; pub type WsStream = WebSocketStream<ConnectStream>;
@@ -23,7 +35,7 @@ pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
Json(JsonError), Json(JsonError),
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
Tls(RustlsError), Tls(RustlsError),
/// The discord voice gateway does not support or offer zlib compression. /// The discord voice gateway does not support or offer zlib compression.
@@ -41,7 +53,7 @@ impl From<JsonError> for Error {
} }
} }
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
impl From<RustlsError> for Error { impl From<RustlsError> for Error {
fn from(e: RustlsError) -> Error { fn from(e: RustlsError) -> Error {
Error::Tls(e) Error::Tls(e)
@@ -55,7 +67,7 @@ impl From<TungsteniteError> for Error {
} }
use futures::stream::SplitSink; use futures::stream::SplitSink;
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
use std::{ use std::{
error::Error as StdError, error::Error as StdError,
fmt::{Display, Formatter, Result as FmtResult}, fmt::{Display, Formatter, Result as FmtResult},
@@ -77,7 +89,7 @@ pub trait SenderExt {
#[async_trait] #[async_trait]
impl ReceiverExt for WsStream { impl ReceiverExt for WsStream {
async fn recv_json(&mut self) -> Result<Option<Event>> { async fn recv_json(&mut self) -> Result<Option<Event>> {
const TIMEOUT: tokio::time::Duration = tokio::time::Duration::from_millis(500); const TIMEOUT: Duration = Duration::from_millis(500);
let ws_message = match timeout(TIMEOUT, self.next()).await { let ws_message = match timeout(TIMEOUT, self.next()).await {
Ok(Some(Ok(v))) => Some(v), Ok(Some(Ok(v))) => Some(v),
@@ -138,7 +150,7 @@ pub(crate) fn convert_ws_message(message: Option<Message>) -> Result<Option<Even
/// An error that occured while connecting over rustls /// An error that occured while connecting over rustls
#[derive(Debug)] #[derive(Debug)]
#[non_exhaustive] #[non_exhaustive]
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
pub enum RustlsError { pub enum RustlsError {
/// An error with the handshake in tungstenite /// An error with the handshake in tungstenite
HandshakeError, HandshakeError,
@@ -146,14 +158,14 @@ pub enum RustlsError {
Io(IoError), Io(IoError),
} }
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
impl From<IoError> for RustlsError { impl From<IoError> for RustlsError {
fn from(e: IoError) -> Self { fn from(e: IoError) -> Self {
RustlsError::Io(e) RustlsError::Io(e)
} }
} }
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
impl Display for RustlsError { impl Display for RustlsError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self { match self {
@@ -164,7 +176,7 @@ impl Display for RustlsError {
} }
} }
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
impl StdError for RustlsError { impl StdError for RustlsError {
fn source(&self) -> Option<&(dyn StdError + 'static)> { fn source(&self) -> Option<&(dyn StdError + 'static)> {
match self { match self {
@@ -174,12 +186,12 @@ impl StdError for RustlsError {
} }
} }
#[cfg(all(feature = "rustls", not(feature = "native")))] #[cfg(all(feature = "rustls-marker", not(feature = "native-marker")))]
#[instrument] #[instrument]
pub(crate) async fn create_rustls_client(url: Url) -> Result<WsStream> { pub(crate) async fn create_rustls_client(url: Url) -> Result<WsStream> {
let (stream, _) = async_tungstenite::tokio::connect_async_with_config::<Url>( let (stream, _) = tungstenite::tokio::connect_async_with_config::<Url>(
url, url,
Some(async_tungstenite::tungstenite::protocol::WebSocketConfig { Some(tungstenite::tungstenite::protocol::WebSocketConfig {
max_message_size: None, max_message_size: None,
max_frame_size: None, max_frame_size: None,
max_send_queue: None, max_send_queue: None,
@@ -191,12 +203,12 @@ pub(crate) async fn create_rustls_client(url: Url) -> Result<WsStream> {
Ok(stream) Ok(stream)
} }
#[cfg(feature = "native")] #[cfg(feature = "native-marker")]
#[instrument] #[instrument]
pub(crate) async fn create_native_tls_client(url: Url) -> Result<WsStream> { pub(crate) async fn create_native_tls_client(url: Url) -> Result<WsStream> {
let (stream, _) = async_tungstenite::tokio::connect_async_with_config::<Url>( let (stream, _) = tungstenite::tokio::connect_async_with_config::<Url>(
url, url,
Some(async_tungstenite::tungstenite::protocol::WebSocketConfig { Some(tungstenite::tungstenite::protocol::WebSocketConfig {
max_message_size: None, max_message_size: None,
max_frame_size: None, max_frame_size: None,
max_send_queue: None, max_send_queue: None,