feat: Public api! (sorta)
This commit is contained in:
parent
17f5456841
commit
ba4818dbad
|
@ -94,6 +94,12 @@ pub struct GatewayEvent<T: WebSocketEvent> {
|
|||
}
|
||||
|
||||
impl<T: WebSocketEvent> GatewayEvent<T> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
observers: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the GatewayEvent is observed by at least one Observer.
|
||||
pub fn is_observed(&self) -> bool {
|
||||
!self.observers.is_empty()
|
||||
|
|
|
@ -14,7 +14,7 @@ pub struct Speaking {
|
|||
///
|
||||
/// See [SpeakingBitFlags]
|
||||
pub speaking: u8,
|
||||
pub ssrc: i32,
|
||||
pub ssrc: u32,
|
||||
/// The user id of the speaking user, only sent by the server
|
||||
#[serde(skip_serializing)]
|
||||
pub user_id: Option<Snowflake>,
|
||||
|
|
|
@ -2,12 +2,9 @@
|
|||
//!
|
||||
//! All functions in this module return a 24 byte long [Vec<u8>].
|
||||
|
||||
use discortp::Packet;
|
||||
|
||||
/// Gets an xsalsa20poly1305 nonce from an rtppacket.
|
||||
pub(crate) fn get_xsalsa20_poly1305_nonce(packet: discortp::rtp::RtpPacket) -> Vec<u8> {
|
||||
|
||||
let mut rtp_header = packet.packet()[0..12].to_vec();
|
||||
pub(crate) fn get_xsalsa20_poly1305_nonce(packet: &[u8]) -> Vec<u8> {
|
||||
let mut rtp_header = packet[0..12].to_vec();
|
||||
|
||||
// The header is only 12 bytes, but the nonce has to be 24
|
||||
// This actually works mind you, and anything else doesn't
|
||||
|
|
|
@ -671,13 +671,16 @@ struct VoiceHeartbeatThreadCommunication {
|
|||
}
|
||||
|
||||
pub mod voice_events {
|
||||
use crate::types::{
|
||||
SessionDescription, SessionUpdate, VoiceBackendVersion, VoiceClientConnectFlags,
|
||||
VoiceClientConnectPlatform, VoiceClientDisconnection, VoiceMediaSinkWants, VoiceReady,
|
||||
use crate::{
|
||||
errors::VoiceGatewayError,
|
||||
gateway::GatewayEvent,
|
||||
types::{
|
||||
SessionDescription, SessionUpdate, Speaking, SsrcDefinition, VoiceBackendVersion,
|
||||
VoiceClientConnectFlags, VoiceClientConnectPlatform, VoiceClientDisconnection,
|
||||
VoiceMediaSinkWants, VoiceReady,
|
||||
},
|
||||
};
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Default, Debug)]
|
||||
pub struct VoiceEvents {
|
||||
pub voice_ready: GatewayEvent<VoiceReady>,
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
//! Module for all voice functionality within chorus.
|
||||
|
||||
mod crypto;
|
||||
pub mod gateway;
|
||||
pub mod udp;
|
||||
pub mod voice_data;
|
||||
mod crypto;
|
||||
|
||||
// Pub use this so users can interact with packet types if they want
|
||||
pub use discortp;
|
||||
|
|
138
src/voice/udp.rs
138
src/voice/udp.rs
|
@ -1,11 +1,16 @@
|
|||
//! Defines voice raw udp socket handling
|
||||
|
||||
use self::voice_udp_events::VoiceUDPEvents;
|
||||
|
||||
use super::crypto;
|
||||
|
||||
use std::{net::SocketAddr, sync::Arc};
|
||||
|
||||
use log::{debug, info, trace, warn};
|
||||
use tokio::{net::UdpSocket, sync::RwLock};
|
||||
use tokio::{
|
||||
net::UdpSocket,
|
||||
sync::{Mutex, RwLock},
|
||||
};
|
||||
|
||||
use crypto_secretbox::{
|
||||
aead::Aead, cipher::generic_array::GenericArray, KeyInit, XSalsa20Poly1305,
|
||||
|
@ -14,6 +19,7 @@ use crypto_secretbox::{
|
|||
use discortp::{
|
||||
demux::{demux, Demuxed},
|
||||
discord::{IpDiscovery, IpDiscoveryPacket, IpDiscoveryType, MutableIpDiscoveryPacket},
|
||||
rtcp::report::{ReceiverReport, SenderReport},
|
||||
Packet,
|
||||
};
|
||||
|
||||
|
@ -28,6 +34,7 @@ const RTP_HEADER_SIZE: u8 = 12;
|
|||
/// Can be safely cloned and will still correspond to the same connection.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UdpHandle {
|
||||
pub events: Arc<Mutex<VoiceUDPEvents>>,
|
||||
socket: Arc<UdpSocket>,
|
||||
pub data: Arc<RwLock<VoiceData>>,
|
||||
}
|
||||
|
@ -75,14 +82,17 @@ impl UdpHandle {
|
|||
|
||||
/// Encrypts and sends and rtp packet.
|
||||
pub async fn send_rtp_packet(&self, packet: discortp::rtp::MutableRtpPacket<'_>) {
|
||||
let mut mutable_packet = packet;
|
||||
self.encrypt_rtp_packet(&mut mutable_packet).await;
|
||||
self.send_encrypted_rtp_packet(mutable_packet.consume_to_immutable())
|
||||
let mut buffer = self.encrypt_rtp_packet_payload(&packet).await;
|
||||
let new_packet = discortp::rtp::MutableRtpPacket::new(&mut buffer).unwrap();
|
||||
self.send_encrypted_rtp_packet(new_packet.consume_to_immutable())
|
||||
.await;
|
||||
}
|
||||
|
||||
/// Encrypts an unecnrypted rtp packet, mutating its payload.
|
||||
pub async fn encrypt_rtp_packet(&self, packet: &mut discortp::rtp::MutableRtpPacket<'_>) {
|
||||
/// Encrypts an unencrypted rtp packet, returning an encrypted copy if its payload.
|
||||
pub async fn encrypt_rtp_packet_payload(
|
||||
&self,
|
||||
packet: &discortp::rtp::MutableRtpPacket<'_>,
|
||||
) -> Vec<u8> {
|
||||
let payload = packet.payload();
|
||||
|
||||
let data_lock = self.data.read().await;
|
||||
|
@ -97,7 +107,7 @@ impl UdpHandle {
|
|||
|
||||
let session_description = session_description_result.unwrap();
|
||||
|
||||
let nonce_bytes = crypto::get_xsalsa20_poly1305_nonce(packet.to_immutable());
|
||||
let nonce_bytes = crypto::get_xsalsa20_poly1305_nonce(packet.packet());
|
||||
let nonce = GenericArray::from_slice(&nonce_bytes);
|
||||
|
||||
let key = GenericArray::from_slice(&session_description.secret_key);
|
||||
|
@ -113,7 +123,18 @@ impl UdpHandle {
|
|||
|
||||
let encrypted_payload = encryption_result.unwrap();
|
||||
|
||||
packet.set_payload(&encrypted_payload);
|
||||
// We need to allocate a new buffer, since the old one is too small for our new encrypted
|
||||
// data
|
||||
let mut new_buffer = packet.packet().to_vec();
|
||||
|
||||
let buffer_size = encrypted_payload.len() + RTP_HEADER_SIZE as usize;
|
||||
|
||||
// Fill the buffer
|
||||
while new_buffer.len() <= buffer_size {
|
||||
new_buffer.push(0);
|
||||
}
|
||||
|
||||
new_buffer
|
||||
}
|
||||
|
||||
/// Sends an (already encrypted) rtp packet to the connection.
|
||||
|
@ -121,11 +142,14 @@ impl UdpHandle {
|
|||
let raw_bytes = packet.packet();
|
||||
|
||||
self.socket.send(raw_bytes).await.unwrap();
|
||||
|
||||
debug!("VUDP: Sent rtp packet!");
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct UdpHandler {
|
||||
events: Arc<Mutex<VoiceUDPEvents>>,
|
||||
pub data: Arc<RwLock<VoiceData>>,
|
||||
socket: Arc<UdpSocket>,
|
||||
}
|
||||
|
@ -207,7 +231,11 @@ impl UdpHandler {
|
|||
|
||||
let socket = Arc::new(udp_socket);
|
||||
|
||||
let events = VoiceUDPEvents::default();
|
||||
let shared_events = Arc::new(Mutex::new(events));
|
||||
|
||||
let mut handler = UdpHandler {
|
||||
events: shared_events.clone(),
|
||||
data: data_reference.clone(),
|
||||
socket: socket.clone(),
|
||||
};
|
||||
|
@ -218,6 +246,7 @@ impl UdpHandler {
|
|||
});
|
||||
|
||||
UdpHandle {
|
||||
events: shared_events,
|
||||
socket,
|
||||
data: data_reference,
|
||||
}
|
||||
|
@ -252,11 +281,7 @@ impl UdpHandler {
|
|||
match parsed {
|
||||
Demuxed::Rtp(rtp) => {
|
||||
let ciphertext = buf[12..buf.len()].to_vec();
|
||||
trace!(
|
||||
"VUDP: Parsed packet as rtp! {:?}; data: {:?}",
|
||||
rtp,
|
||||
ciphertext
|
||||
);
|
||||
trace!("VUDP: Parsed packet as rtp!");
|
||||
|
||||
let data_lock = self.data.read().await;
|
||||
|
||||
|
@ -273,7 +298,7 @@ impl UdpHandler {
|
|||
|
||||
match session_description.encryption_mode {
|
||||
crate::types::VoiceEncryptionMode::Xsalsa20Poly1305 => {
|
||||
nonce_bytes = crypto::get_xsalsa20_poly1305_nonce(rtp);
|
||||
nonce_bytes = crypto::get_xsalsa20_poly1305_nonce(rtp.packet());
|
||||
}
|
||||
_ => {
|
||||
unimplemented!();
|
||||
|
@ -298,10 +323,66 @@ impl UdpHandler {
|
|||
|
||||
let decrypted = decryption_result.unwrap();
|
||||
|
||||
info!("VUDP: SUCCESSFULLY DECRYPTED VOICE DATA!!! {:?}", decrypted);
|
||||
debug!("VUDP: Successfully decrypted voice data!");
|
||||
|
||||
let rtp_with_decrypted_data = discortp::rtp::Rtp {
|
||||
ssrc: rtp.get_ssrc(),
|
||||
marker: rtp.get_marker(),
|
||||
version: rtp.get_version(),
|
||||
padding: rtp.get_padding(),
|
||||
sequence: rtp.get_sequence(),
|
||||
extension: rtp.get_extension(),
|
||||
timestamp: rtp.get_timestamp(),
|
||||
csrc_list: rtp.get_csrc_list(),
|
||||
csrc_count: rtp.get_csrc_count(),
|
||||
payload_type: rtp.get_payload_type(),
|
||||
payload: decrypted,
|
||||
};
|
||||
|
||||
self.events
|
||||
.lock()
|
||||
.await
|
||||
.rtp
|
||||
.notify(rtp_with_decrypted_data)
|
||||
.await;
|
||||
}
|
||||
Demuxed::Rtcp(rtcp) => {
|
||||
trace!("VUDP: Parsed packet as rtcp! {:?}", rtcp);
|
||||
trace!("VUDP: Parsed packet as rtcp!");
|
||||
|
||||
let rtcp_data;
|
||||
|
||||
match rtcp {
|
||||
discortp::rtcp::RtcpPacket::KnownType(knowntype) => {
|
||||
rtcp_data = discortp::rtcp::Rtcp::KnownType(knowntype);
|
||||
}
|
||||
discortp::rtcp::RtcpPacket::SenderReport(senderreport) => {
|
||||
rtcp_data = discortp::rtcp::Rtcp::SenderReport(SenderReport {
|
||||
payload: senderreport.payload().to_vec(),
|
||||
padding: senderreport.get_padding(),
|
||||
version: senderreport.get_version(),
|
||||
ssrc: senderreport.get_ssrc(),
|
||||
pkt_length: senderreport.get_pkt_length(),
|
||||
packet_type: senderreport.get_packet_type(),
|
||||
rx_report_count: senderreport.get_rx_report_count(),
|
||||
});
|
||||
}
|
||||
discortp::rtcp::RtcpPacket::ReceiverReport(receiverreport) => {
|
||||
rtcp_data = discortp::rtcp::Rtcp::ReceiverReport(ReceiverReport {
|
||||
payload: receiverreport.payload().to_vec(),
|
||||
padding: receiverreport.get_padding(),
|
||||
version: receiverreport.get_version(),
|
||||
ssrc: receiverreport.get_ssrc(),
|
||||
pkt_length: receiverreport.get_pkt_length(),
|
||||
packet_type: receiverreport.get_packet_type(),
|
||||
rx_report_count: receiverreport.get_rx_report_count(),
|
||||
});
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
|
||||
self.events.lock().await.rtcp.notify(rtcp_data).await;
|
||||
}
|
||||
Demuxed::FailedParse(e) => {
|
||||
trace!("VUDP: Failed to parse packet: {:?}", e);
|
||||
|
@ -312,3 +393,28 @@ impl UdpHandler {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod voice_udp_events {
|
||||
|
||||
use discortp::{rtcp::Rtcp, rtp::Rtp};
|
||||
|
||||
use crate::{gateway::GatewayEvent, types::WebSocketEvent};
|
||||
|
||||
impl WebSocketEvent for Rtp {}
|
||||
impl WebSocketEvent for Rtcp {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct VoiceUDPEvents {
|
||||
pub rtp: GatewayEvent<Rtp>,
|
||||
pub rtcp: GatewayEvent<Rtcp>,
|
||||
}
|
||||
|
||||
impl Default for VoiceUDPEvents {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
rtp: GatewayEvent::new(),
|
||||
rtcp: GatewayEvent::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue