Optimized 1.4.11

This commit is contained in:
WolverinDEV 2020-03-25 20:36:44 +01:00
parent d52496600f
commit c627690011
9 changed files with 171 additions and 83 deletions

@ -1 +1 @@
Subproject commit c3a2818a7f698f3a0efbf32426924299214106da Subproject commit 71efb006ebdce2740e652306df36e34465a21dfc

View File

@ -235,7 +235,7 @@ target_link_libraries(PermMapHelper
SET(CPACK_PACKAGE_VERSION_MAJOR "1") SET(CPACK_PACKAGE_VERSION_MAJOR "1")
SET(CPACK_PACKAGE_VERSION_MINOR "4") SET(CPACK_PACKAGE_VERSION_MINOR "4")
SET(CPACK_PACKAGE_VERSION_PATCH "10") SET(CPACK_PACKAGE_VERSION_PATCH "11")
if (BUILD_TYPE_NAME EQUAL OFF) if (BUILD_TYPE_NAME EQUAL OFF)
SET(CPACK_PACKAGE_VERSION_DATA "beta") SET(CPACK_PACKAGE_VERSION_DATA "beta")
elseif (BUILD_TYPE_NAME STREQUAL "") elseif (BUILD_TYPE_NAME STREQUAL "")

View File

@ -309,6 +309,32 @@ int main(int argc, char** argv) {
logMessageFmt(true, LOG_GENERAL, strobf("[]---------------------------------------------------------[]").string()); 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 TeaSpeak-Server v{}", build::version()->string(true));
logMessage(LOG_GENERAL, "Starting music providers"); logMessage(LOG_GENERAL, "Starting music providers");

View File

@ -529,51 +529,66 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
CMD_CHK_AND_INC_FLOOD_POINTS(25); CMD_CHK_AND_INC_FLOOD_POINTS(25);
CMD_CHK_PARM_COUNT(1); CMD_CHK_PARM_COUNT(1);
//TODO: Use for this here the cache as well! std::shared_ptr<TreeView::LinkedTreeEntry> parent = nullptr;
auto permission_cache = make_shared<CalculateCache>(); std::shared_ptr<BasicChannel> created_channel = nullptr, old_default_channel;
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);
auto target_tree = this->server ? this->server->channelTree : serverInstance->getChannelTree().get(); auto target_tree = this->server ? this->server->channelTree : serverInstance->getChannelTree().get();
auto& tree_lock = this->server ? this->server->channel_tree_lock : serverInstance->getChannelTreeLock(); auto& tree_lock = this->server ? this->server->channel_tree_lock : serverInstance->getChannelTreeLock();
unique_lock tree_channel_lock(tree_lock); 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")) { if(cmd[0].has("channel_conversation_history_length")) {
auto value = cmd["channel_conversation_history_length"].as<int64_t>(); auto value = cmd["channel_conversation_history_length"].as<int64_t>();
if(value == 0) { 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 { } 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 else
cmd["channel_delete_delay"] = 0; cmd["channel_delete_delay"] = 0;
} else { } 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; 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>()) if(this->server && created_total >= this->server->properties()[property::VIRTUALSERVER_MAX_CHANNELS].as<uint64_t>())
return command_result{error::channel_limit_reached}; 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(max_channels.has_value) {
if(!permission::v2::permission_granted(created_perm + created_semi + created_tmp + 1, max_channels)) if(!permission::v2::permission_granted(created_perm + created_semi + created_tmp + 1, max_channels))
return command_result{permission::i_client_max_channels}; return command_result{permission::i_client_max_channels};
} }
if (cmd[0]["channel_flag_permanent"].as<bool>()) { 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(max_channels.has_value) {
if(!permission::v2::permission_granted(created_perm + 1, max_channels)) 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>()) { 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(max_channels.has_value) {
if(!permission::v2::permission_granted(created_semi + 1, max_channels)) if(!permission::v2::permission_granted(created_semi + 1, max_channels))
@ -630,7 +646,7 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
} }
} }
else { 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(max_channels.has_value) {
if(!permission::v2::permission_granted(created_tmp + 1, max_channels)) 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) //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 //bool enforce_permanent_parent = cmd[0]["channel_flag_default"].as<bool>(); //TODO check parents here
{ //Checkout the parent(s) { //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 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, 0, 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) { if(min_channel_deep.has_value || max_channel_deep.has_value) {
auto channel_deep = 0; auto channel_deep = 0;
@ -704,8 +712,8 @@ command_result ConnectedClient::handleCommandChannelCreate(Command &cmd) {
created_channel->properties()[property::CHANNEL_CREATED_BY] = this->getClientDatabaseId(); 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_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, 0, 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(); auto permission_manager = created_channel->permissions();
permission_manager->set_permission( permission_manager->set_permission(

View File

@ -1,8 +1,7 @@
#include <misc/std_unique_ptr.h> #include <misc/std_unique_ptr.h>
#include <log/LogUtils.h> #include <log/LogUtils.h>
#include <pipes/rtc/PeerConnection.h>
#include <pipes/rtc/AudioStream.h>
#include <misc/endianness.h> #include <misc/endianness.h>
#include <dlfcn.h>
#include "WebClient.h" #include "WebClient.h"
#include "VoiceBridge.h" #include "VoiceBridge.h"
@ -11,7 +10,7 @@ using namespace ts;
using namespace ts::server; using namespace ts::server;
using namespace ts::web; 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; auto max_length = 1024 * 8;
char buffer[max_length]; 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); max_length = vsnprintf(buffer, max_length, message.c_str(), args);
va_end(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) { 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->allow_ice_tcp = false;
config->nice_config->use_upnp = config::web::enable_upnp; config->nice_config->use_upnp = config::web::enable_upnp;
//FIXME Use the internal thread or a shared worker gioloop::initialize();
/* Not creating the thread here because DataPipes has a better impl with a join 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); 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(); std::thread(g_main_loop_run, config->nice_config->main_loop.get()).detach();
*/ */
config->logger = make_shared<pipes::Logger>(); 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 //config->sctp.local_port = 5202; //Fire Fox don't support a different port :D
this->connection = make_unique<rtc::PeerConnection>(config); 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) { 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); debugMessage(this->server_id(), "{} WebRTC setup failed! Component {} ({})", CLIENT_STR_LOG_PREFIX_(this->owner()), comp, reason);
if(this->callback_failed) 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) { 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; 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? 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) { } 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; if(!stream) return;
this->_audio_channel = stream; this->_audio_channel = stream;
stream->register_local_extension("urn:ietf:params:rtp-hdrext:ssrc-audio-level"); 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? for(const auto& codec : stream->list_codecs()) {
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); }; 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 { } else {
logError(this->server_id(), "Got offer for unknown channel of type {}", undefined_stream->type()); 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) { 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::TypedAudio::OPUS) { if(channel->codec->type != rtc::codec::Codec::OPUS) {
debugMessage(this->server_id(), "{} Got unknown codec ({})!", CLIENT_STR_LOG_PREFIX_(this->owner()), channel->codec->type); debugMessage(this->server_id(), "{} Got unknown codec ({})!", CLIENT_STR_LOG_PREFIX_(this->owner()), channel->codec->type);
return; return;
} }
@ -172,7 +220,7 @@ void VoiceBridge::handle_audio_data(const std::shared_ptr<rtc::AudioChannel> &ch
auto ac = _audio_channel.lock(); auto ac = _audio_channel.lock();
if(!ac) return; 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") { if(ext->name == "urn:ietf:params:rtp-hdrext:ssrc-audio-level") {
int level; int level;
if(rtc::protocol::rtp_header_extension_parse_audio_level(data, ext->id, &level) == 0) { if(rtc::protocol::rtp_header_extension_parse_audio_level(data, ext->id, &level) == 0) {

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include <pipes/rtc/PeerConnection.h> #include <pipes/rtc/PeerConnection.h>
#include <pipes/rtc/ApplicationStream.h> #include <pipes/rtc/channels/ApplicationChannel.h>
#include <pipes/rtc/AudioStream.h> #include <pipes/rtc/channels/AudioChannel.h>
namespace ts { namespace ts {
namespace server { namespace server {
@ -36,19 +36,20 @@ namespace ts {
void execute_tick(); void execute_tick();
private: private:
static void callback_log(void* ptr, pipes::Logger::LogLevel level, const std::string& name, const std::string& message, ...);
inline int server_id(); inline int server_id();
inline std::shared_ptr<server::WebClient> owner(); 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_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::weak_ptr<server::WebClient> _owner;
std::chrono::system_clock::time_point offer_timestamp; std::chrono::system_clock::time_point offer_timestamp;
std::unique_ptr<rtc::PeerConnection> connection; std::unique_ptr<rtc::PeerConnection> connection;
std::shared_ptr<rtc::DataChannel> _voice_channel; std::shared_ptr<rtc::DataChannel> _voice_channel;
std::weak_ptr<rtc::AudioStream> _audio_channel; std::weak_ptr<rtc::AudioChannel> _audio_channel;
struct { struct {
uint16_t packet_id = 0; uint16_t packet_id = 0;
bool muted = true; bool muted = true;

View File

@ -476,8 +476,11 @@ void WebClient::handleMessage(const std::string &message) {
auto vb_ptr = &*this->voice_bridge; /* read only no lock needed */ auto vb_ptr = &*this->voice_bridge; /* read only no lock needed */
std::thread([&, vb_ptr, lock = this->ref()]{ std::thread([&, vb_ptr, lock = this->ref()]{
unique_lock vbl{this->voice_bridge_lock}; unique_lock vbl{this->voice_bridge_lock};
if(&*this->voice_bridge == vb_ptr) if(&*this->voice_bridge == vb_ptr) {
this->voice_bridge.release(); auto bridge = std::exchange(this->voice_bridge, nullptr);
vbl.unlock();
bridge.reset();
}
}).detach(); }).detach();
Json::Value response; Json::Value response;
@ -551,7 +554,7 @@ void WebClient::handleMessage(const std::string &message) {
this->sendJson(response); this->sendJson(response);
} }
} else if(subType == "ice") { } 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) { if(!this->voice_bridge) {
debugMessage(this->getServerId(), "[{}] Received remote ICE candidate without having a voice bridge! Dropping candidate.", CLIENT_STR_LOG_PREFIX); debugMessage(this->getServerId(), "[{}] Received remote ICE candidate without having a voice bridge! Dropping candidate.", CLIENT_STR_LOG_PREFIX);
return; return;
@ -578,7 +581,7 @@ void WebClient::handleMessage(const std::string &message) {
} }
} }
} else if(subType == "ice_finish") { } 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) { if(!this->voice_bridge) {
debugMessage(this->getServerId(), "[{}] Received remote ICE candidate without having a voice bridge! Dropping candidate.", CLIENT_STR_LOG_PREFIX); debugMessage(this->getServerId(), "[{}] Received remote ICE candidate without having a voice bridge! Dropping candidate.", CLIENT_STR_LOG_PREFIX);
return; return;

View File

@ -222,7 +222,7 @@ namespace ts {
class ConversationManager { class ConversationManager {
public: public:
ConversationManager(const std::shared_ptr<VirtualServer>& /* server */); explicit ConversationManager(const std::shared_ptr<VirtualServer>& /* server */);
virtual ~ConversationManager(); virtual ~ConversationManager();
void initialize(const std::shared_ptr<ConversationManager>& _this); void initialize(const std::shared_ptr<ConversationManager>& _this);

View File

@ -473,8 +473,10 @@ namespace terminal {
if(cmd.arguments.size() < 1) { if(cmd.arguments.size() < 1) {
value = 1024; value = 1024;
rlimit limit{1024, 10000}; rlimit rlimit{0, 0};
setrlimit(7, &limit); getrlimit(RLIMIT_NOFILE, &rlimit);
logMessage("RLimit: {}/{}", rlimit.rlim_cur, rlimit.rlim_max);
//setrlimit(7, &limit);
} else if(cmd.larguments[0] == "clear") { } else if(cmd.larguments[0] == "clear") {
logMessage("Clearup leaks"); logMessage("Clearup leaks");
for(auto& fd : fd_leaks) for(auto& fd : fd_leaks)