From e93b8715f9e42d25c0930becc22561f23a25a709 Mon Sep 17 00:00:00 2001 From: ouwou <26526779+ouwou@users.noreply.github.com> Date: Mon, 5 Sep 2022 02:21:37 -0400 Subject: basic voice capture + transmission --- src/discord/voiceclient.cpp | 38 +++++++++++++++++++++++++++++++------- src/discord/voiceclient.hpp | 19 +++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) (limited to 'src/discord') diff --git a/src/discord/voiceclient.cpp b/src/discord/voiceclient.cpp index d8855fd..3f38eea 100644 --- a/src/discord/voiceclient.cpp +++ b/src/discord/voiceclient.cpp @@ -43,11 +43,11 @@ void UDPSocket::SetSSRC(uint32_t ssrc) { m_ssrc = ssrc; } -void UDPSocket::SendEncrypted(const std::vector &data) { +void UDPSocket::SendEncrypted(const uint8_t *data, size_t len) { m_sequence++; - m_timestamp += (48000 / 100) * 2; + m_timestamp += 480; // this is important - std::vector rtp(12, 0); + std::vector rtp(12 + len + crypto_secretbox_MACBYTES, 0); rtp[0] = 0x80; // ver 2 rtp[1] = 0x78; // payload type 0x78 rtp[2] = (m_sequence >> 8) & 0xFF; @@ -63,14 +63,15 @@ void UDPSocket::SendEncrypted(const std::vector &data) { static std::array nonce = {}; std::memcpy(nonce.data(), rtp.data(), 12); - - std::vector ciphertext(crypto_secretbox_MACBYTES + rtp.size(), 0); - crypto_secretbox_easy(ciphertext.data(), rtp.data(), rtp.size(), nonce.data(), m_secret_key.data()); - rtp.insert(rtp.end(), ciphertext.begin(), ciphertext.end()); + crypto_secretbox_easy(rtp.data() + 12, data, len, nonce.data(), m_secret_key.data()); Send(rtp.data(), rtp.size()); } +void UDPSocket::SendEncrypted(const std::vector &data) { + SendEncrypted(data.data(), data.size()); +} + void UDPSocket::Send(const uint8_t *data, size_t len) { sendto(m_socket, reinterpret_cast(data), static_cast(len), 0, reinterpret_cast(&m_server), sizeof(m_server)); } @@ -172,6 +173,14 @@ DiscordVoiceClient::~DiscordVoiceClient() { void DiscordVoiceClient::Start() { m_ws.StartConnection("wss://" + m_endpoint + "/?v=7"); + + // cant put in ctor or deadlock in singleton initialization + auto &aud = Abaddon::Get().GetAudio(); + aud.SetOpusBuffer(m_opus_buffer.data()); + aud.signal_opus_packet().connect([this](int payload_size) { + if (m_connected) + m_udp.SendEncrypted(m_opus_buffer.data(), payload_size); + }); } void DiscordVoiceClient::SetSessionID(std::string_view session_id) { @@ -241,6 +250,13 @@ void DiscordVoiceClient::HandleGatewaySessionDescription(const VoiceGatewayMessa printf("%02X", b); } printf("\n"); + + VoiceSpeakingMessage msg; + msg.Delay = 0; + msg.SSRC = m_ssrc; + msg.Speaking = VoiceSpeakingMessage::Microphone; + m_ws.Send(msg); + m_secret_key = d.SecretKey; m_udp.SetSSRC(m_ssrc); m_udp.SetSecretKey(m_secret_key); @@ -250,6 +266,7 @@ void DiscordVoiceClient::HandleGatewaySessionDescription(const VoiceGatewayMessa m_udp.SendEncrypted({ 0xF8, 0xFF, 0xFE }); m_udp.SendEncrypted({ 0xF8, 0xFF, 0xFE }); m_udp.Run(); + m_connected = true; } void DiscordVoiceClient::Identify() { @@ -388,4 +405,11 @@ void from_json(const nlohmann::json &j, VoiceSessionDescriptionData &m) { JS_D("mode", m.Mode); JS_D("secret_key", m.SecretKey); } + +void to_json(nlohmann::json &j, const VoiceSpeakingMessage &m) { + j["op"] = VoiceGatewayOp::Speaking; + j["d"]["speaking"] = m.Speaking; + j["d"]["delay"] = m.Delay; + j["d"]["ssrc"] = m.SSRC; +} #endif diff --git a/src/discord/voiceclient.hpp b/src/discord/voiceclient.hpp index 4b988d5..67919e5 100644 --- a/src/discord/voiceclient.hpp +++ b/src/discord/voiceclient.hpp @@ -110,6 +110,20 @@ struct VoiceSessionDescriptionData { friend void from_json(const nlohmann::json &j, VoiceSessionDescriptionData &m); }; +struct VoiceSpeakingMessage { + enum { + Microphone = 1 << 0, + Soundshare = 1 << 1, + Priority = 1 << 2, + }; + + int Speaking; + int Delay; + uint32_t SSRC; + + friend void to_json(nlohmann::json &j, const VoiceSpeakingMessage &m); +}; + class UDPSocket { public: UDPSocket(); @@ -119,6 +133,7 @@ public: void Run(); void SetSecretKey(std::array key); void SetSSRC(uint32_t ssrc); + void SendEncrypted(const uint8_t *data, size_t len); void SendEncrypted(const std::vector &data); void Send(const uint8_t *data, size_t len); std::vector Receive(); @@ -205,5 +220,9 @@ private: int m_heartbeat_msec; Waiter m_heartbeat_waiter; std::thread m_heartbeat_thread; + + std::array m_opus_buffer; + + std::atomic m_connected = false; }; #endif -- cgit v1.2.3