Optimized 1.4.11
This commit is contained in:
parent
d52496600f
commit
c627690011
@ -1 +1 @@
|
||||
Subproject commit c3a2818a7f698f3a0efbf32426924299214106da
|
||||
Subproject commit 71efb006ebdce2740e652306df36e34465a21dfc
|
@ -235,7 +235,7 @@ target_link_libraries(PermMapHelper
|
||||
|
||||
SET(CPACK_PACKAGE_VERSION_MAJOR "1")
|
||||
SET(CPACK_PACKAGE_VERSION_MINOR "4")
|
||||
SET(CPACK_PACKAGE_VERSION_PATCH "10")
|
||||
SET(CPACK_PACKAGE_VERSION_PATCH "11")
|
||||
if (BUILD_TYPE_NAME EQUAL OFF)
|
||||
SET(CPACK_PACKAGE_VERSION_DATA "beta")
|
||||
elseif (BUILD_TYPE_NAME STREQUAL "")
|
||||
|
@ -309,6 +309,32 @@ int main(int argc, char** argv) {
|
||||
logMessageFmt(true, LOG_GENERAL, strobf("[]---------------------------------------------------------[]").string());
|
||||
}
|
||||
|
||||
{
|
||||
rlimit rlimit{0, 0};
|
||||
//forum.teaspeak.de/index.php?threads/2570/
|
||||
constexpr auto seek_help_message = "Fore more help visit the forum and read this thread (https://forum.teaspeak.de/index.php?threads/2570/).";
|
||||
if(getrlimit(RLIMIT_NOFILE, &rlimit) != 0) {
|
||||
//prlimit -n4096 -p pid_of_process
|
||||
logWarningFmt(true, LOG_INSTANCE, "Failed to get open file rlimit ({}). Please ensure its over 16384.", strerror(errno));
|
||||
logWarningFmt(true, LOG_INSTANCE, seek_help_message);
|
||||
} else {
|
||||
const auto original = rlimit.rlim_cur;
|
||||
rlimit.rlim_cur = std::max(rlimit.rlim_cur, std::min(rlimit.rlim_max, (rlim_t) 16384));
|
||||
if(original != rlimit.rlim_cur) {
|
||||
if(setrlimit(RLIMIT_NOFILE, &rlimit) != 0) {
|
||||
logErrorFmt(true, LOG_INSTANCE, "Failed to set open file rlimit to {} ({}). Please ensure its over 16384.", rlimit.rlim_cur, strerror(errno));
|
||||
logWarningFmt(true, LOG_INSTANCE, seek_help_message);
|
||||
goto rlimit_updates;
|
||||
}
|
||||
}
|
||||
if(rlimit.rlim_cur < 16384) {
|
||||
logWarningFmt(true, LOG_INSTANCE, "Open file rlimit is bellow 16384 ({}). Please increase the system file descriptor limits.", rlimit.rlim_cur);
|
||||
logWarningFmt(true, LOG_INSTANCE, seek_help_message);
|
||||
}
|
||||
}
|
||||
rlimit_updates:;
|
||||
}
|
||||
|
||||
logMessage(LOG_GENERAL, "Starting TeaSpeak-Server v{}", build::version()->string(true));
|
||||
logMessage(LOG_GENERAL, "Starting music providers");
|
||||
|
||||
|
@ -529,51 +529,66 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(25);
|
||||
CMD_CHK_PARM_COUNT(1);
|
||||
|
||||
//TODO: Use for this here the cache as well!
|
||||
auto permission_cache = make_shared<CalculateCache>();
|
||||
if (cmd[0].has("cpid") && cmd["cpid"].as<uint64_t>() != 0) ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_child, 1, permission_cache);
|
||||
if (cmd[0].has("channel_order")) ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_with_sortorder, 1, permission_cache);
|
||||
|
||||
if(!cmd[0].has("channel_flag_permanent")) cmd[0]["channel_flag_permanent"] = false;
|
||||
if(!cmd[0].has("channel_flag_semi_permanent")) cmd[0]["channel_flag_semi_permanent"] = false;
|
||||
if(!cmd[0].has("channel_flag_default")) cmd[0]["channel_flag_default"] = false;
|
||||
if(!cmd[0].has("channel_flag_password")) cmd[0]["channel_flag_password"] = false;
|
||||
|
||||
if (cmd[0]["channel_flag_permanent"].as<bool>()) ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_permanent, 1, permission_cache);
|
||||
else if (cmd[0]["channel_flag_semi_permanent"].as<bool>()) ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_semi_permanent, 1, permission_cache);
|
||||
else ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_temporary, 1, permission_cache);
|
||||
|
||||
if (!cmd[0]["channel_flag_permanent"].as<bool>() && !this->server) return command_result{error::parameter_invalid, "You can only create a permanent channel"};
|
||||
|
||||
if (cmd[0]["channel_flag_default"].as<bool>()) ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_with_default, 1, permission_cache);
|
||||
if (cmd[0]["channel_flag_password"].as<bool>()) ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_with_password, 1, permission_cache);
|
||||
else if(permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_create_modify_with_force_password, 0, false, permission_cache)))
|
||||
return command_result{permission::b_channel_create_modify_with_force_password};
|
||||
|
||||
if(cmd[0].has("channel_password") && this->getType() == ClientType::CLIENT_QUERY)
|
||||
cmd["channel_password"] = base64::decode(digest::sha1(cmd["channel_password"].string()));
|
||||
if (cmd[0].has("channel_description")) ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_with_description, 1, permission_cache);
|
||||
if (cmd[0].has("channel_maxclients") || (cmd[0].has("channel_flag_maxclients_unlimited") && !cmd["channel_flag_maxclients_unlimited"].as<bool>())) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_with_maxclients, 1, permission_cache);
|
||||
if(!cmd[0]["channel_flag_permanent"].as<bool>() && !cmd[0]["channel_flag_semi_permanent"].as<bool>()) {
|
||||
cmd["channel_maxclients"] = -1;
|
||||
cmd["channel_flag_maxclients_unlimited"] = 1;
|
||||
}
|
||||
}
|
||||
if (cmd[0].has("channel_maxfamilyclients")) ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_with_maxfamilyclients, 1, permission_cache);
|
||||
if (cmd[0].has("channel_needed_talk_power")) ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_with_needed_talk_power, 1, permission_cache);
|
||||
if (cmd[0].has("channel_topic")) ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_with_topic, 1, permission_cache);
|
||||
std::shared_ptr<TreeView::LinkedTreeEntry> parent = nullptr;
|
||||
std::shared_ptr<BasicChannel> created_channel = nullptr, old_default_channel;
|
||||
|
||||
auto target_tree = this->server ? this->server->channelTree : serverInstance->getChannelTree().get();
|
||||
auto& tree_lock = this->server ? this->server->channel_tree_lock : serverInstance->getChannelTreeLock();
|
||||
unique_lock tree_channel_lock(tree_lock);
|
||||
|
||||
if (cmd[0].has("cpid") && cmd["cpid"].as<ChannelId>() != 0 && cmd["cpid"].as<int>() != -1) {
|
||||
parent = target_tree->findLinkedChannel(cmd["cpid"].as<ChannelId>());
|
||||
if (!parent) return command_result{error::channel_invalid_id, "Cant resolve parent channel"};
|
||||
}
|
||||
ChannelId parent_channel_id = parent ? parent->entry->channelId() : 0;
|
||||
|
||||
#define test_permission(required, permission_type) \
|
||||
do {\
|
||||
if(!permission::v2::permission_granted(required, this->calculate_permission(permission_type, parent_channel_id, false, permission_cache))) \
|
||||
return command_result{permission_type};\
|
||||
} while(0)
|
||||
|
||||
|
||||
//TODO: Use for this here the cache as well!
|
||||
auto permission_cache = make_shared<CalculateCache>();
|
||||
if(parent) test_permission(1, permission::b_channel_create_child);
|
||||
if (cmd[0].has("channel_order")) test_permission(1, permission::b_channel_create_with_sortorder);
|
||||
if(!cmd[0].has("channel_flag_permanent")) cmd[0]["channel_flag_permanent"] = false;
|
||||
if(!cmd[0].has("channel_flag_semi_permanent")) cmd[0]["channel_flag_semi_permanent"] = false;
|
||||
if(!cmd[0].has("channel_flag_default")) cmd[0]["channel_flag_default"] = false;
|
||||
if(!cmd[0].has("channel_flag_password")) cmd[0]["channel_flag_password"] = false;
|
||||
|
||||
if (cmd[0]["channel_flag_permanent"].as<bool>()) test_permission(1, permission::b_channel_create_permanent);
|
||||
else if (cmd[0]["channel_flag_semi_permanent"].as<bool>()) test_permission(1, permission::b_channel_create_semi_permanent);
|
||||
else test_permission(1, permission::b_channel_create_temporary);
|
||||
|
||||
if (!cmd[0]["channel_flag_permanent"].as<bool>() && !this->server) return command_result{error::parameter_invalid, "You can only create a permanent channel"};
|
||||
|
||||
if (cmd[0]["channel_flag_default"].as<bool>()) test_permission(1, permission::b_channel_create_with_default);
|
||||
if (cmd[0]["channel_flag_password"].as<bool>()) test_permission(1, permission::b_channel_create_with_password);
|
||||
else if(permission::v2::permission_granted(1, this->calculate_permission(permission::b_channel_create_modify_with_force_password, parent_channel_id, false, permission_cache)))
|
||||
return command_result{permission::b_channel_create_modify_with_force_password};
|
||||
|
||||
if(cmd[0].has("channel_password") && this->getType() == ClientType::CLIENT_QUERY)
|
||||
cmd["channel_password"] = base64::decode(digest::sha1(cmd["channel_password"].string()));
|
||||
if (cmd[0].has("channel_description")) test_permission(1, permission::b_channel_create_with_description);
|
||||
if (cmd[0].has("channel_maxclients") || (cmd[0].has("channel_flag_maxclients_unlimited") && !cmd["channel_flag_maxclients_unlimited"].as<bool>())) {
|
||||
test_permission(1, permission::b_channel_create_with_maxclients);
|
||||
if(!cmd[0]["channel_flag_permanent"].as<bool>() && !cmd[0]["channel_flag_semi_permanent"].as<bool>()) {
|
||||
cmd["channel_maxclients"] = -1;
|
||||
cmd["channel_flag_maxclients_unlimited"] = 1;
|
||||
}
|
||||
}
|
||||
if (cmd[0].has("channel_maxfamilyclients")) test_permission(1, permission::b_channel_create_with_maxfamilyclients);
|
||||
if (cmd[0].has("channel_needed_talk_power")) test_permission(1,permission::b_channel_create_with_needed_talk_power);
|
||||
if (cmd[0].has("channel_topic")) test_permission(1,permission::b_channel_create_with_topic);
|
||||
|
||||
if(cmd[0].has("channel_conversation_history_length")) {
|
||||
auto value = cmd["channel_conversation_history_length"].as<int64_t>();
|
||||
if(value == 0) {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::b_channel_create_modify_conversation_history_unlimited, 1, permission_cache);
|
||||
test_permission(1, permission::b_channel_create_modify_conversation_history_unlimited);
|
||||
} else {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::i_channel_create_modify_conversation_history_length, 1, permission_cache);
|
||||
test_permission(1, permission::i_channel_create_modify_conversation_history_length);
|
||||
}
|
||||
}
|
||||
|
||||
@ -585,9 +600,10 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
else
|
||||
cmd["channel_delete_delay"] = 0;
|
||||
} else {
|
||||
ACTION_REQUIRES_GLOBAL_PERMISSION_CACHED(permission::i_channel_create_modify_with_temp_delete_delay, cmd["channel_delete_delay"].as<permission::PermissionValue>(), permission_cache);
|
||||
test_permission(cmd["channel_delete_delay"].as<permission::PermissionValue>(), permission::i_channel_create_modify_with_temp_delete_delay);
|
||||
}
|
||||
}
|
||||
#undef test_permission
|
||||
|
||||
{
|
||||
size_t created_total = 0, created_tmp = 0, created_semi = 0, created_perm = 0;
|
||||
@ -607,14 +623,14 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
if(this->server && created_total >= this->server->properties()[property::VIRTUALSERVER_MAX_CHANNELS].as<uint64_t>())
|
||||
return command_result{error::channel_limit_reached};
|
||||
|
||||
auto max_channels = this->calculate_permission(permission::i_client_max_channels, 0, false, permission_cache);
|
||||
auto max_channels = this->calculate_permission(permission::i_client_max_channels, parent_channel_id, false, permission_cache);
|
||||
if(max_channels.has_value) {
|
||||
if(!permission::v2::permission_granted(created_perm + created_semi + created_tmp + 1, max_channels))
|
||||
return command_result{permission::i_client_max_channels};
|
||||
}
|
||||
|
||||
if (cmd[0]["channel_flag_permanent"].as<bool>()) {
|
||||
max_channels = this->calculate_permission(permission::i_client_max_permanent_channels, 0, false, permission_cache);
|
||||
max_channels = this->calculate_permission(permission::i_client_max_permanent_channels, parent_channel_id, false, permission_cache);
|
||||
|
||||
if(max_channels.has_value) {
|
||||
if(!permission::v2::permission_granted(created_perm + 1, max_channels))
|
||||
@ -622,7 +638,7 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
}
|
||||
}
|
||||
else if (cmd[0]["channel_flag_semi_permanent"].as<bool>()) {
|
||||
max_channels = this->calculate_permission(permission::i_client_max_semi_channels, 0, false, permission_cache);
|
||||
max_channels = this->calculate_permission(permission::i_client_max_semi_channels, parent_channel_id, false, permission_cache);
|
||||
|
||||
if(max_channels.has_value) {
|
||||
if(!permission::v2::permission_granted(created_semi + 1, max_channels))
|
||||
@ -630,7 +646,7 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
max_channels = this->calculate_permission(permission::i_client_max_temporary_channels, 0, false, permission_cache);
|
||||
max_channels = this->calculate_permission(permission::i_client_max_temporary_channels, parent_channel_id, false, permission_cache);
|
||||
|
||||
if(max_channels.has_value) {
|
||||
if(!permission::v2::permission_granted(created_tmp + 1, max_channels))
|
||||
@ -640,20 +656,12 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
}
|
||||
|
||||
//TODO check voice (opus etc)
|
||||
std::shared_ptr<TreeView::LinkedTreeEntry> parent = nullptr;
|
||||
std::shared_ptr<BasicChannel> created_channel = nullptr, old_default_channel;
|
||||
|
||||
//bool enforce_permanent_parent = cmd[0]["channel_flag_default"].as<bool>(); //TODO check parents here
|
||||
{ //Checkout the parent(s)
|
||||
if (cmd[0].has("cpid") && cmd["cpid"].as<ChannelId>() != 0 && cmd["cpid"].as<int>() != -1) {
|
||||
parent = target_tree->findLinkedChannel(cmd["cpid"].as<ChannelId>());
|
||||
if (!parent) return command_result{error::channel_invalid_id, "Cant resolve parent channel"};
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
auto min_channel_deep = this->calculate_permission(permission::i_channel_min_depth, 0, false, permission_cache);
|
||||
auto max_channel_deep = this->calculate_permission(permission::i_channel_max_depth, 0, false, permission_cache);
|
||||
auto min_channel_deep = this->calculate_permission(permission::i_channel_min_depth, parent_channel_id, false, permission_cache);
|
||||
auto max_channel_deep = this->calculate_permission(permission::i_channel_max_depth, parent_channel_id, false, permission_cache);
|
||||
|
||||
if(min_channel_deep.has_value || max_channel_deep.has_value) {
|
||||
auto channel_deep = 0;
|
||||
@ -704,8 +712,8 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
|
||||
created_channel->properties()[property::CHANNEL_CREATED_BY] = this->getClientDatabaseId();
|
||||
|
||||
{
|
||||
auto default_modify_power = this->calculate_permission(permission::i_channel_modify_power, 0, false, permission_cache);
|
||||
auto default_delete_power = this->calculate_permission(permission::i_channel_delete_power, 0, false, permission_cache);
|
||||
auto default_modify_power = this->calculate_permission(permission::i_channel_modify_power, parent_channel_id, false, permission_cache);
|
||||
auto default_delete_power = this->calculate_permission(permission::i_channel_delete_power, parent_channel_id, false, permission_cache);
|
||||
|
||||
auto permission_manager = created_channel->permissions();
|
||||
permission_manager->set_permission(
|
||||
|
@ -1,8 +1,7 @@
|
||||
#include <misc/std_unique_ptr.h>
|
||||
#include <log/LogUtils.h>
|
||||
#include <pipes/rtc/PeerConnection.h>
|
||||
#include <pipes/rtc/AudioStream.h>
|
||||
#include <misc/endianness.h>
|
||||
#include <dlfcn.h>
|
||||
#include "WebClient.h"
|
||||
#include "VoiceBridge.h"
|
||||
|
||||
@ -11,7 +10,7 @@ using namespace ts;
|
||||
using namespace ts::server;
|
||||
using namespace ts::web;
|
||||
|
||||
void log(pipes::Logger::LogLevel level, const std::string& name, const std::string& message, ...) {
|
||||
void VoiceBridge::callback_log(void* ptr, pipes::Logger::LogLevel level, const std::string& name, const std::string& message, ...) {
|
||||
auto max_length = 1024 * 8;
|
||||
char buffer[max_length];
|
||||
|
||||
@ -20,7 +19,49 @@ void log(pipes::Logger::LogLevel level, const std::string& name, const std::stri
|
||||
max_length = vsnprintf(buffer, max_length, message.c_str(), args);
|
||||
va_end(args);
|
||||
|
||||
debugMessage(LOG_GENERAL, "[WebRTC][{}][{}] {}", level, name, string(buffer));
|
||||
auto bridge = (VoiceBridge*) ptr;
|
||||
debugMessage(LOG_GENERAL, "{}[WebRTC][{}][{}] {}", CLIENT_STR_LOG_PREFIX_(bridge->owner()), level, name, string(buffer));
|
||||
}
|
||||
|
||||
namespace gioloop {
|
||||
void* main_loop_;
|
||||
|
||||
void*(*g_main_loop_new)(void* /* context */, bool /* is true */);
|
||||
void(*g_main_loop_run)(void* /* loop */);
|
||||
void(*g_main_loop_unref)(void* /* loop */);
|
||||
void*(*g_main_loop_ref)(void* /* loop */);
|
||||
|
||||
bool initialized{false};
|
||||
void initialize() {
|
||||
if(initialized) return;
|
||||
initialized = true;
|
||||
|
||||
g_main_loop_new = (decltype(g_main_loop_new)) dlsym(nullptr, "g_main_loop_new");
|
||||
g_main_loop_run = (decltype(g_main_loop_run)) dlsym(nullptr, "g_main_loop_run");
|
||||
g_main_loop_ref = (decltype(g_main_loop_ref)) dlsym(nullptr, "g_main_loop_ref");
|
||||
g_main_loop_unref = (decltype(g_main_loop_unref)) dlsym(nullptr, "g_main_loop_unref");
|
||||
|
||||
if(!g_main_loop_run || !g_main_loop_new || !g_main_loop_ref || !g_main_loop_unref) {
|
||||
logWarning(LOG_INSTANCE, "Missing g_main_loop_new, g_main_loop_run, g_main_loop_ref or g_main_loop_unref functions. Could not spawn main loop.");
|
||||
g_main_loop_run = nullptr;
|
||||
g_main_loop_new = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
main_loop_ = g_main_loop_new(nullptr, false);
|
||||
if(!main_loop_) {
|
||||
logError(LOG_INSTANCE, "Failed to spawn new event loop for the web client.");
|
||||
return;
|
||||
}
|
||||
|
||||
std::thread([]{
|
||||
g_main_loop_run(main_loop_);
|
||||
}).detach();
|
||||
}
|
||||
|
||||
std::shared_ptr<GMainLoop> loop() {
|
||||
return std::shared_ptr<GMainLoop>{(GMainLoop*) g_main_loop_ref(main_loop_), g_main_loop_unref};
|
||||
}
|
||||
}
|
||||
|
||||
VoiceBridge::VoiceBridge(const shared_ptr<WebClient>& owner) : _owner(owner) {
|
||||
@ -48,14 +89,16 @@ VoiceBridge::VoiceBridge(const shared_ptr<WebClient>& owner) : _owner(owner) {
|
||||
config->nice_config->allow_ice_tcp = false;
|
||||
config->nice_config->use_upnp = config::web::enable_upnp;
|
||||
|
||||
//FIXME Use the internal thread or a shared worker
|
||||
/* Not creating the thread here because DataPipes has a better impl with a join
|
||||
gioloop::initialize();
|
||||
config->nice_config->main_loop = gioloop::loop();
|
||||
/*
|
||||
config->nice_config->main_loop = std::shared_ptr<GMainLoop>(g_main_loop_new(nullptr, false), g_main_loop_unref);
|
||||
std::thread(g_main_loop_run, config->nice_config->main_loop.get()).detach();
|
||||
*/
|
||||
|
||||
config->logger = make_shared<pipes::Logger>();
|
||||
config->logger->callback_log = log;
|
||||
config->logger->callback_log = VoiceBridge::callback_log;
|
||||
config->logger->callback_argument = this;
|
||||
//config->sctp.local_port = 5202; //Fire Fox don't support a different port :D
|
||||
|
||||
this->connection = make_unique<rtc::PeerConnection>(config);
|
||||
@ -87,7 +130,7 @@ bool VoiceBridge::initialize(std::string &error) {
|
||||
}
|
||||
};
|
||||
|
||||
this->connection->callback_new_stream = [&](const std::shared_ptr<rtc::Stream> &channel) { this->handle_media_stream(channel); }; //bind(&VoiceBridge::handle_media_stream, this, placeholders::_1); => crash
|
||||
this->connection->callback_new_stream = [&](const std::shared_ptr<rtc::Channel> &channel) { this->handle_media_stream(channel); }; //bind(&VoiceBridge::handle_media_stream, this, placeholders::_1); => crash
|
||||
this->connection->callback_setup_fail = [&](rtc::PeerConnection::ConnectionComponent comp, const std::string& reason) {
|
||||
debugMessage(this->server_id(), "{} WebRTC setup failed! Component {} ({})", CLIENT_STR_LOG_PREFIX_(this->owner()), comp, reason);
|
||||
if(this->callback_failed)
|
||||
@ -123,20 +166,25 @@ void VoiceBridge::execute_tick() {
|
||||
}
|
||||
}
|
||||
|
||||
void VoiceBridge::handle_media_stream(const std::shared_ptr<rtc::Stream> &undefined_stream) {
|
||||
void VoiceBridge::handle_media_stream(const std::shared_ptr<rtc::Channel> &undefined_stream) {
|
||||
if(undefined_stream->type() == rtc::CHANTYPE_APPLICATION) {
|
||||
auto stream = dynamic_pointer_cast<rtc::ApplicationStream>(undefined_stream);
|
||||
auto stream = dynamic_pointer_cast<rtc::ApplicationChannel>(undefined_stream);
|
||||
if(!stream) return;
|
||||
|
||||
stream->callback_datachannel_new = [&](const std::shared_ptr<rtc::DataChannel> &channel) { this->handle_data_channel(channel); }; //bind(&VoiceBridge::handle_data_channel, this, placeholders::_1); => may crash?
|
||||
} else if(undefined_stream->type() == rtc::CHANTYPE_AUDIO) {
|
||||
auto stream = dynamic_pointer_cast<rtc::AudioStream>(undefined_stream);
|
||||
auto stream = dynamic_pointer_cast<rtc::AudioChannel>(undefined_stream);
|
||||
if(!stream) return;
|
||||
this->_audio_channel = stream;
|
||||
|
||||
stream->register_local_extension("urn:ietf:params:rtp-hdrext:ssrc-audio-level");
|
||||
//bind(&VoiceBridge::handle_audio_data, this, placeholders::_1, placeholders::_2, placeholders::_3); => may crash?
|
||||
stream->incoming_data_handler = [&](const std::shared_ptr<rtc::AudioChannel> &channel, const pipes::buffer_view &data, size_t payload_offset) { this->handle_audio_data(channel, data, payload_offset); };
|
||||
for(const auto& codec : stream->list_codecs()) {
|
||||
if(codec->type == rtc::codec::Codec::OPUS) {
|
||||
codec->accepted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
stream->incoming_data_handler = [&](const std::shared_ptr<rtc::MediaChannel> &channel, const pipes::buffer_view &data, size_t payload_offset) { this->handle_audio_data(channel, data, payload_offset); };
|
||||
} else {
|
||||
logError(this->server_id(), "Got offer for unknown channel of type {}", undefined_stream->type());
|
||||
}
|
||||
@ -163,8 +211,8 @@ void VoiceBridge::handle_data_channel(const std::shared_ptr<rtc::DataChannel> &c
|
||||
};
|
||||
}
|
||||
|
||||
void VoiceBridge::handle_audio_data(const std::shared_ptr<rtc::AudioChannel> &channel, const pipes::buffer_view &data, size_t payload_offset) {
|
||||
if(channel->codec->type != rtc::codec::TypedAudio::OPUS) {
|
||||
void VoiceBridge::handle_audio_data(const std::shared_ptr<rtc::MediaChannel> &channel, const pipes::buffer_view &data, size_t payload_offset) {
|
||||
if(channel->codec->type != rtc::codec::Codec::OPUS) {
|
||||
debugMessage(this->server_id(), "{} Got unknown codec ({})!", CLIENT_STR_LOG_PREFIX_(this->owner()), channel->codec->type);
|
||||
return;
|
||||
}
|
||||
@ -172,7 +220,7 @@ void VoiceBridge::handle_audio_data(const std::shared_ptr<rtc::AudioChannel> &ch
|
||||
auto ac = _audio_channel.lock();
|
||||
if(!ac) return;
|
||||
|
||||
for(const auto& ext : ac->list_extensions(0x02)) {
|
||||
for(const auto& ext : ac->list_extensions(rtc::direction::incoming)) {
|
||||
if(ext->name == "urn:ietf:params:rtp-hdrext:ssrc-audio-level") {
|
||||
int level;
|
||||
if(rtc::protocol::rtp_header_extension_parse_audio_level(data, ext->id, &level) == 0) {
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <pipes/rtc/PeerConnection.h>
|
||||
#include <pipes/rtc/ApplicationStream.h>
|
||||
#include <pipes/rtc/AudioStream.h>
|
||||
#include <pipes/rtc/channels/ApplicationChannel.h>
|
||||
#include <pipes/rtc/channels/AudioChannel.h>
|
||||
|
||||
namespace ts {
|
||||
namespace server {
|
||||
@ -36,19 +36,20 @@ namespace ts {
|
||||
|
||||
void execute_tick();
|
||||
private:
|
||||
static void callback_log(void* ptr, pipes::Logger::LogLevel level, const std::string& name, const std::string& message, ...);
|
||||
|
||||
inline int server_id();
|
||||
inline std::shared_ptr<server::WebClient> owner();
|
||||
|
||||
void handle_media_stream(const std::shared_ptr<rtc::Stream>& /* stream */);
|
||||
void handle_media_stream(const std::shared_ptr<rtc::Channel>& /* stream */);
|
||||
void handle_data_channel(const std::shared_ptr<rtc::DataChannel> & /* channel */);
|
||||
void handle_audio_data(const std::shared_ptr<rtc::AudioChannel>& /* channel */, const pipes::buffer_view& /* buffer */, size_t /* payload offset */);
|
||||
void handle_audio_data(const std::shared_ptr<rtc::MediaChannel>& /* channel */, const pipes::buffer_view& /* buffer */, size_t /* payload offset */);
|
||||
|
||||
std::weak_ptr<server::WebClient> _owner;
|
||||
std::chrono::system_clock::time_point offer_timestamp;
|
||||
std::unique_ptr<rtc::PeerConnection> connection;
|
||||
std::shared_ptr<rtc::DataChannel> _voice_channel;
|
||||
std::weak_ptr<rtc::AudioStream> _audio_channel;
|
||||
std::weak_ptr<rtc::AudioChannel> _audio_channel;
|
||||
struct {
|
||||
uint16_t packet_id = 0;
|
||||
bool muted = true;
|
||||
|
@ -476,8 +476,11 @@ void WebClient::handleMessage(const std::string &message) {
|
||||
auto vb_ptr = &*this->voice_bridge; /* read only no lock needed */
|
||||
std::thread([&, vb_ptr, lock = this->ref()]{
|
||||
unique_lock vbl{this->voice_bridge_lock};
|
||||
if(&*this->voice_bridge == vb_ptr)
|
||||
this->voice_bridge.release();
|
||||
if(&*this->voice_bridge == vb_ptr) {
|
||||
auto bridge = std::exchange(this->voice_bridge, nullptr);
|
||||
vbl.unlock();
|
||||
bridge.reset();
|
||||
}
|
||||
}).detach();
|
||||
|
||||
Json::Value response;
|
||||
@ -551,7 +554,7 @@ void WebClient::handleMessage(const std::string &message) {
|
||||
this->sendJson(response);
|
||||
}
|
||||
} else if(subType == "ice") {
|
||||
shared_lock read_voice_bridge_lock(this->voice_bridge_lock);
|
||||
std::shared_lock read_voice_bridge_lock{this->voice_bridge_lock};
|
||||
if(!this->voice_bridge) {
|
||||
debugMessage(this->getServerId(), "[{}] Received remote ICE candidate without having a voice bridge! Dropping candidate.", CLIENT_STR_LOG_PREFIX);
|
||||
return;
|
||||
@ -578,7 +581,7 @@ void WebClient::handleMessage(const std::string &message) {
|
||||
}
|
||||
}
|
||||
} else if(subType == "ice_finish") {
|
||||
shared_lock read_voice_bridge_lock(this->voice_bridge_lock);
|
||||
std::shared_lock read_voice_bridge_lock{this->voice_bridge_lock};
|
||||
if(!this->voice_bridge) {
|
||||
debugMessage(this->getServerId(), "[{}] Received remote ICE candidate without having a voice bridge! Dropping candidate.", CLIENT_STR_LOG_PREFIX);
|
||||
return;
|
||||
|
@ -222,7 +222,7 @@ namespace ts {
|
||||
|
||||
class ConversationManager {
|
||||
public:
|
||||
ConversationManager(const std::shared_ptr<VirtualServer>& /* server */);
|
||||
explicit ConversationManager(const std::shared_ptr<VirtualServer>& /* server */);
|
||||
virtual ~ConversationManager();
|
||||
|
||||
void initialize(const std::shared_ptr<ConversationManager>& _this);
|
||||
|
@ -473,8 +473,10 @@ namespace terminal {
|
||||
if(cmd.arguments.size() < 1) {
|
||||
value = 1024;
|
||||
|
||||
rlimit limit{1024, 10000};
|
||||
setrlimit(7, &limit);
|
||||
rlimit rlimit{0, 0};
|
||||
getrlimit(RLIMIT_NOFILE, &rlimit);
|
||||
logMessage("RLimit: {}/{}", rlimit.rlim_cur, rlimit.rlim_max);
|
||||
//setrlimit(7, &limit);
|
||||
} else if(cmd.larguments[0] == "clear") {
|
||||
logMessage("Clearup leaks");
|
||||
for(auto& fd : fd_leaks)
|
||||
|
Loading…
Reference in New Issue
Block a user