From ed01cf57699c212baa64c368fb264392b43a220a Mon Sep 17 00:00:00 2001 From: Craig Edwards Date: Thu, 3 Oct 2024 22:56:49 +0000 Subject: [PATCH] split out ip discoverey and improve it from a bunch of punning --- src/dpp/discordvoiceclient.cpp | 41 ------------ src/dpp/voice/enabled/discover_ip.cpp | 94 +++++++++++++++++++++++++++ src/dpp/voice/stub/constructor.cpp | 61 ----------------- src/dpp/voice/stub/stubs.cpp | 10 +++ 4 files changed, 104 insertions(+), 102 deletions(-) create mode 100644 src/dpp/voice/enabled/discover_ip.cpp delete mode 100644 src/dpp/voice/stub/constructor.cpp diff --git a/src/dpp/discordvoiceclient.cpp b/src/dpp/discordvoiceclient.cpp index 1bdbd3ea4c..a542d84e32 100644 --- a/src/dpp/discordvoiceclient.cpp +++ b/src/dpp/discordvoiceclient.cpp @@ -420,47 +420,6 @@ uint64_t discord_voice_client::get_timescale() { return timescale; } -std::string discord_voice_client::discover_ip() { - dpp::socket newfd = SOCKET_ERROR; - unsigned char packet[74] = { 0 }; - (*(uint16_t*)(packet)) = htons(0x01); - (*(uint16_t*)(packet + 2)) = htons(70); - (*(uint32_t*)(packet + 4)) = htonl((uint32_t)this->ssrc); - if ((newfd = ::socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { - sockaddr_in servaddr{}; - memset(&servaddr, 0, sizeof(sockaddr_in)); - servaddr.sin_family = AF_INET; - servaddr.sin_addr.s_addr = htonl(INADDR_ANY); - servaddr.sin_port = htons(0); - if (bind(newfd, (sockaddr*)&servaddr, sizeof(servaddr)) < 0) { - log(ll_warning, "Could not bind socket for IP discovery"); - return ""; - } - memset(&servaddr, 0, sizeof(servaddr)); - servaddr.sin_family = AF_INET; - servaddr.sin_port = htons(this->port); - servaddr.sin_addr.s_addr = inet_addr(this->ip.c_str()); - if (::connect(newfd, (const sockaddr*)&servaddr, sizeof(sockaddr_in)) < 0) { - log(ll_warning, "Could not connect socket for IP discovery"); - return ""; - } - if (::send(newfd, (const char*)packet, 74, 0) == -1) { - log(ll_warning, "Could not send packet for IP discovery"); - return ""; - } - if (recv(newfd, (char*)packet, 74, 0) == -1) { - log(ll_warning, "Could not receive packet for IP discovery"); - return ""; - } - - close_socket(newfd); - - //utility::debug_dump(packet, 74); - return std::string((const char*)(packet + 8)); - } - return ""; -} - discord_voice_client& discord_voice_client::set_iteration_interval(uint16_t interval) { this->iteration_interval = interval; return *this; diff --git a/src/dpp/voice/enabled/discover_ip.cpp b/src/dpp/voice/enabled/discover_ip.cpp new file mode 100644 index 0000000000..ea503216b6 --- /dev/null +++ b/src/dpp/voice/enabled/discover_ip.cpp @@ -0,0 +1,94 @@ +/************************************************************************************ + * + * D++, A Lightweight C++ library for Discord + * + * SPDX-License-Identifier: Apache-2.0 + * Copyright 2021 Craig Edwards and D++ contributors + * (https://github.com/brainboxdotcc/DPP/graphs/contributors) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ************************************************************************************/ + +#include +#include +#include "enabled.h" + +namespace dpp { + +/** + * https://discord.com/developers/docs/topics/voice-connections#ip-discovery + */ + +#pragma pack(push, 1) +struct ip_discovery_packet { + uint16_t type; + uint16_t length; + uint32_t ssrc; + char address[64]{0}; // NOLINT + uint16_t port; + + ip_discovery_packet() = delete; + + ip_discovery_packet(uint32_t _ssrc) : + type(htons(0x01)), length(htons(sizeof(ip_discovery_packet) - sizeof(type) - sizeof(length))), + ssrc(htonl(_ssrc)), port(0) { + std::memset(&address, 0, sizeof(address)); + } +}; +#pragma pack(pop) + +std::string discord_voice_client::discover_ip() { + + if (!external_ip.empty()) { + return external_ip; + } + + dpp::socket newfd = SOCKET_ERROR; + ip_discovery_packet discovery((uint32_t)this->ssrc); + + if ((newfd = ::socket(AF_INET, SOCK_DGRAM, 0)) >= 0) { + sockaddr_in servaddr{}; + memset(&servaddr, 0, sizeof(sockaddr_in)); + servaddr.sin_family = AF_INET; + servaddr.sin_addr.s_addr = htonl(INADDR_ANY); + servaddr.sin_port = htons(0); + if (bind(newfd, (sockaddr*)&servaddr, sizeof(servaddr)) < 0) { + log(ll_warning, "Could not bind socket for IP discovery"); + return ""; + } + memset(&servaddr, 0, sizeof(servaddr)); + servaddr.sin_family = AF_INET; + servaddr.sin_port = htons(this->port); + servaddr.sin_addr.s_addr = inet_addr(this->ip.c_str()); + if (::connect(newfd, (const sockaddr*)&servaddr, sizeof(sockaddr_in)) < 0) { + log(ll_warning, "Could not connect socket for IP discovery"); + return ""; + } + if (::send(newfd, reinterpret_cast(&discovery), sizeof(discovery), 0) == -1) { + log(ll_warning, "Could not send packet for IP discovery"); + return ""; + } + if (recv(newfd, reinterpret_cast(&discovery), sizeof(discovery), 0) == -1) { + log(ll_warning, "Could not receive packet for IP discovery"); + return ""; + } + + close_socket(newfd); + + return {discovery.address, strlen(discovery.address)}; + } + return {}; +} + +} \ No newline at end of file diff --git a/src/dpp/voice/stub/constructor.cpp b/src/dpp/voice/stub/constructor.cpp deleted file mode 100644 index b763521377..0000000000 --- a/src/dpp/voice/stub/constructor.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/************************************************************************************ - * - * D++, A Lightweight C++ library for Discord - * - * SPDX-License-Identifier: Apache-2.0 - * Copyright 2021 Craig Edwards and D++ contributors - * (https://github.com/brainboxdotcc/DPP/graphs/contributors) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ************************************************************************************/ - -#include -#include - -#include "stub.h" - -namespace dpp { - -discord_voice_client::discord_voice_client(dpp::cluster* _cluster, snowflake _channel_id, snowflake _server_id, const std::string &_token, const std::string &_session_id, const std::string &_host, bool enable_dave) - : websocket_client(_host.substr(0, _host.find(':')), _host.substr(_host.find(':') + 1, _host.length()), "/?v=" + std::to_string(voice_protocol_version), OP_TEXT), - runner(nullptr), - connect_time(0), - mixer(nullptr), - port(0), - ssrc(0), - timescale(1000000), - paused(false), - encoder(nullptr), - repacketizer(nullptr), - fd(INVALID_SOCKET), - sequence(0), - receive_sequence(-1), - timestamp(0), - packet_nonce(1), - last_timestamp(std::chrono::high_resolution_clock::now()), - sending(false), - tracks(0), - creator(_cluster), - terminating(false), - heartbeat_interval(0), - last_heartbeat(time(nullptr)), - token(_token), - sessionid(_session_id), - server_id(_server_id), - channel_id(_channel_id) -{ - throw dpp::voice_exception(err_no_voice_support, "Voice support not enabled in this build of D++"); -} - -} \ No newline at end of file diff --git a/src/dpp/voice/stub/stubs.cpp b/src/dpp/voice/stub/stubs.cpp index 67f10072df..0e310f2b4f 100644 --- a/src/dpp/voice/stub/stubs.cpp +++ b/src/dpp/voice/stub/stubs.cpp @@ -27,6 +27,12 @@ namespace dpp { + discord_voice_client::discord_voice_client(dpp::cluster* _cluster, snowflake _channel_id, snowflake _server_id, const std::string &_token, const std::string &_session_id, const std::string &_host, bool enable_dave) + : websocket_client(_host.substr(0, _host.find(':')), _host.substr(_host.find(':') + 1, _host.length()), "/?v=" + std::to_string(voice_protocol_version), OP_TEXT) + { + throw dpp::voice_exception(err_no_voice_support, "Voice support not enabled in this build of D++"); + } + void discord_voice_client::voice_courier_loop(discord_voice_client& client, courier_shared_state_t& shared_state) { } @@ -89,4 +95,8 @@ namespace dpp { return 0; } + std::string discord_voice_client::discover_ip() { + return ""; + } + } \ No newline at end of file