Fixed a crash and using properly the Nan::HandlerScropes in async callbacks

This commit is contained in:
WolverinDEV 2019-07-24 01:03:01 +02:00
parent 8d3cbbdc3a
commit 2a03857955
16 changed files with 201 additions and 109 deletions

View File

@ -24,6 +24,9 @@ function(setup_nodejs)
set(NODEJS_URL "https://atom.io/download/atom-shell")
set(NODEJS_VERSION "v5.0.6")
#set(NODEJS_URL "https://nodejs.org/download/release/")
#set(NODEJS_VERSION "v12.7.0")
find_package(NodeJS REQUIRED)
set(NODEJS_NAN_DIR "node_modules/nan")
@ -49,7 +52,6 @@ function(setup_nodejs)
set(NODEJS_INIT ${NODEJS_INIT} PARENT_SCOPE)
include_directories("dist/ext_nan")
message("${NODEJS_INCLUDE_DIRS}")
function(add_nodejs_module NAME)
@ -134,7 +136,10 @@ endif()
setup_nodejs()
if(NOT NODEJS_INCLUDE_DIRS OR NODEJS_INCLUDE_DIRS STREQUAL "")
message(FATAL_ERROR "Failed to find node headers")
else()
message("Including NodeJS headers: ${NODEJS_INCLUDE_DIRS}")
endif()
include_directories(${NODEJS_INCLUDE_DIRS})
function(build_update_installer)
add_subdirectory(updater)

37
native/create_symbols.sh Executable file
View File

@ -0,0 +1,37 @@
#!/usr/bin/env bash
cd $(dirname $0)
SYMBOL_ROOT="build/symbols"
BINARY_PATHS=("build/linux_x64/teaclient_connection.node" "build/linux_x64/teaclient_crash_handler.node" "build/linux_x64/teaclient_ppt.node" "build/exe/update-installer")
echo "Created dump symbols!"
for file in ${BINARY_PATHS[@]}; do
if [[ ! -e ${file} ]]; then
echo "Missing binary ${file}. Skipping file"
continue
fi
echo "Generating symbols for ${file}"
symbols="$(dump_syms ${file} 2>&1)"
if [[ $? -ne 0 ]]; then
echo "Failed to dump symbols for ${file}. Skipping file. Output:"
echo "${symbols}"
continue;
fi
symbol_info=$(echo "${symbols}" | head -n1)
symbol_info_array=($symbol_info)
echo "Symbol dump id: ${symbol_info_array[3]}; Dump name: ${symbol_info_array[4]}"
symbol_path="${SYMBOL_ROOT}/${symbol_info_array[4]}/${symbol_info_array[3]}"
symbol_file="${symbol_info_array[4]}.sym"
echo "Saving symbols to ${symbol_path}/${symbol_file}"
mkdir -p ${symbol_path}
[[ $? -ne 0 ]] && {
echo "Failed to create target dump path! Skipping file"
continue
}
echo "${symbols}" > "${symbol_path}/${symbol_file}"
done
echo "All symbols have been created"

View File

@ -30,3 +30,5 @@ if [[ ${machine} == "Linux" ]]; then
rm teaclient_codec.node; ln -s ../../codec/cmake-build-debug/Debug/teaclient_codec.node
rm teaclient_ppt.node; ln -s ../../ppt/cmake-build-debug/Debug/teaclient_ppt.node
fi
#/home/wolverindev/.config/TeaClient/crash_dumps/crash_dump_renderer_04a85069-9d30-48ec-e2fd5e9e-846c5305.dmp

View File

@ -29,37 +29,18 @@ bool OpusConverter::initialize(std::string &error, int application_type) {
void OpusConverter::reset_encoder() {
lock_guard lock(this->coder_lock);
string error;
bool flag_error = false;
if(!(flag_error |= !this->_finalize_encoder(error))) {
error = "finalize failed (" + error + ")";
}
if(!flag_error && !(flag_error |= !this->_initialize_encoder(error))) {
error = "initialize failed (" + error + ")";
}
if(flag_error)
log_warn(category::audio, tr("Failed to reset opus encoder: {}"), error);
auto result = opus_encoder_ctl(this->encoder, OPUS_RESET_STATE);
if(result != OPUS_OK)
log_warn(category::audio, tr("Failed to reset opus encoder. Opus result: {}"), result);
}
void OpusConverter::reset_decoder() {
lock_guard lock(this->coder_lock);
string error;
bool flag_error = false;
if(!(flag_error |= !this->_finalize_decoder(error))) {
error = "finalize failed (" + error + ")";
}
if(!flag_error && !(flag_error |= !this->_initialize_decoder(error))) {
error = "initialize failed (" + error + ")";
}
if(flag_error)
log_warn(category::audio, tr("Failed to reset opus decoder: {}"), error);
auto result = opus_decoder_ctl(this->decoder, OPUS_RESET_STATE);
if(result != OPUS_OK)
log_warn(category::audio, tr("Failed to reset opus decoder. Opus result: {}"), result);
}
@ -85,6 +66,8 @@ ssize_t OpusConverter::encode(std::string &error, const void *source, void *targ
}
ssize_t OpusConverter::decode(std::string &error, const void *source, size_t source_length, void *target) {
lock_guard lock(this->coder_lock);
auto result = opus_decode_float(this->decoder, (uint8_t*) source, (opus_int32) source_length, (float*) target, (int) this->_frame_size, 0);
if(result < OPUS_OK) {
error = to_string(result) + "|" + opus_strerror(result);
@ -94,15 +77,16 @@ ssize_t OpusConverter::decode(std::string &error, const void *source, size_t sou
}
ssize_t OpusConverter::decode_lost(std::string &error, size_t packets) {
auto buffer = (float*) malloc(this->_frame_size * packets * this->_channels * sizeof(float));
auto result = opus_decode_float(this->decoder, nullptr, 0, buffer, this->_frame_size * packets, false);
free(buffer);
lock_guard lock(this->coder_lock);
if(result < OPUS_OK) {
error = to_string(result) + "|" + opus_strerror(result);
return -1;
auto buffer = (float*) malloc(this->_frame_size * this->_channels * sizeof(float));
while (packets-- > 0) {
auto result = opus_decode_float(this->decoder, nullptr, 0, buffer, this->_frame_size, false);
if(result < OPUS_OK)
log_warn(category::audio, tr("Opus decode lost resulted in error: {}"), result);
}
return result;
free(buffer);
return 0;
}
size_t OpusConverter::expected_encoded_length(size_t sample_count) {

View File

@ -61,6 +61,8 @@ void AudioConsumerWrapper::do_wrap(const v8::Local<v8::Object> &obj) {
this->Wrap(obj);
this->_call_data = Nan::async_callback([&] {
Nan::HandleScope scope;
auto handle = this->handle();
v8::Local<v8::Value> callback_function = handle->Get(Nan::New<v8::String>("callback_data").ToLocalChecked());
if(callback_function.IsEmpty() || callback_function->IsNullOrUndefined() || !callback_function->IsFunction()) {
@ -86,24 +88,28 @@ void AudioConsumerWrapper::do_wrap(const v8::Local<v8::Object> &obj) {
v8::Local<v8::Value> argv[1];
argv[0] = js_fbuffer;
callback_function.As<v8::Function>()->Call(Nan::Undefined(), 1, argv);
callback_function.As<v8::Function>()->Call(Nan::GetCurrentContext(), Nan::Undefined(), 1, argv);
}
});
this->_call_ended = Nan::async_callback([&]{
Nan::HandleScope scope;
auto handle = this->handle();
v8::Local<v8::Value> callback_function = handle->Get(Nan::New<v8::String>("callback_ended").ToLocalChecked());
if(callback_function.IsEmpty() || callback_function->IsNullOrUndefined() || !callback_function->IsFunction())
return;
callback_function.As<v8::Function>()->Call(Nan::Undefined(), 0, nullptr);
callback_function.As<v8::Function>()->Call(Nan::GetCurrentContext(), Nan::Undefined(), 0, nullptr);
});
this->_call_started = Nan::async_callback([&]{
Nan::HandleScope scope;
auto handle = this->handle();
v8::Local<v8::Value> callback_function = handle->Get(Nan::New<v8::String>("callback_started").ToLocalChecked());
if(callback_function.IsEmpty() || callback_function->IsNullOrUndefined() || !callback_function->IsFunction())
return;
callback_function.As<v8::Function>()->Call(Nan::Undefined(), 0, nullptr);
callback_function.As<v8::Function>()->Call(Nan::GetCurrentContext(), Nan::Undefined(), 0, nullptr);
});
Nan::Set(this->handle(), Nan::New<v8::String>("frame_size").ToLocalChecked(), Nan::New<v8::Number>(this->_handle->frame_size));
@ -248,7 +254,7 @@ NAN_METHOD(AudioConsumerWrapper::_unregister_filter) {
return;
}
auto consumer = ObjectWrap::Unwrap<AudioFilterWrapper>(info[0]->ToObject());
auto consumer = ObjectWrap::Unwrap<AudioFilterWrapper>(info[0]->ToObject(Nan::GetCurrentContext()).ToLocalChecked());
handle->delete_filter(consumer);
}
@ -265,7 +271,7 @@ NAN_METHOD(AudioConsumerWrapper::_create_filter_vad) {
string error;
auto filter = make_shared<filter::VadFilter>(consumer->channel_count,consumer->sample_rate,consumer->frame_size);
if(!filter->initialize(error, info[0]->Int32Value(), 2)) {
if(!filter->initialize(error, info[0]->Int32Value(Nan::GetCurrentContext()).FromMaybe(0), 2)) {
Nan::ThrowError(Nan::New<v8::String>("failed to initialize filter (" + error + ")").ToLocalChecked());
return;
}
@ -286,7 +292,7 @@ NAN_METHOD(AudioConsumerWrapper::_create_filter_threshold) {
string error;
auto filter = make_shared<filter::ThresholdFilter>(consumer->channel_count,consumer->sample_rate,consumer->frame_size);
if(!filter->initialize(error, info[0]->Int32Value(), 2)) {
if(!filter->initialize(error, info[0]->Int32Value(Nan::GetCurrentContext()).FromMaybe(0), 2)) {
Nan::ThrowError(Nan::New<v8::String>("failed to initialize filter (" + error + ")").ToLocalChecked());
return;
}

View File

@ -48,13 +48,15 @@ AudioFilterWrapper::AudioFilterWrapper(const std::string& name, const std::share
auto threshold_filter = dynamic_pointer_cast<filter::ThresholdFilter>(this->_filter);
if(threshold_filter) {
this->_call_analyzed = Nan::async_callback([&](float value) {
Nan::HandleScope scope;
if(!this->_callback_analyzed.IsEmpty()) {
auto cb = Nan::New<v8::Function>(this->_callback_analyzed);
v8::Local<v8::Value> argv[1];
argv[0] = Nan::New<v8::Number>(value);
cb->Call(Nan::Undefined(), 1, argv);
cb->Call(Nan::GetCurrentContext(), Nan::Undefined(), 1, argv);
}
});
}
@ -132,9 +134,9 @@ NAN_METHOD(AudioFilterWrapper::_set_margin_frames) {
auto vad_filter = dynamic_pointer_cast<filter::VadFilter>(handle->_filter);
auto threshold_filter = dynamic_pointer_cast<filter::ThresholdFilter>(handle->_filter);
if(vad_filter) {
vad_filter->set_margin_frames(info[0]->Int32Value());
vad_filter->set_margin_frames(info[0]->Int32Value(Nan::GetCurrentContext()).FromMaybe(0));
} else if(threshold_filter) {
threshold_filter->set_margin_frames(info[0]->Int32Value());
threshold_filter->set_margin_frames(info[0]->Int32Value(Nan::GetCurrentContext()).FromMaybe(0));
} else {
Nan::ThrowError("invalid handle");
return;
@ -176,7 +178,7 @@ NAN_METHOD(AudioFilterWrapper::_set_threshold) {
return;
}
filter->set_threshold(info[0]->Int32Value());
filter->set_threshold(info[0]->Int32Value(Nan::GetCurrentContext()).FromMaybe(0));
}
NAN_METHOD(AudioFilterWrapper::_get_attack_smooth) {
@ -212,7 +214,7 @@ NAN_METHOD(AudioFilterWrapper::_set_attack_smooth) {
return;
}
filter->attack_smooth(info[0]->NumberValue());
filter->attack_smooth(info[0]->NumberValue(Nan::GetCurrentContext()).FromMaybe(0));
}
NAN_METHOD(AudioFilterWrapper::_get_release_smooth) {
@ -248,7 +250,7 @@ NAN_METHOD(AudioFilterWrapper::_set_release_smooth) {
return;
}
filter->release_smooth(info[0]->NumberValue());
filter->release_smooth(info[0]->NumberValue(Nan::GetCurrentContext()).FromMaybe(0));
}
NAN_METHOD(AudioFilterWrapper::_set_analyze_filter) {
@ -313,5 +315,5 @@ NAN_METHOD(AudioFilterWrapper::_set_consuming) {
return;
}
filter->set_consume_input(info[0]->BooleanValue());
filter->set_consume_input(info[0]->BooleanValue(info.GetIsolate()));
}

View File

@ -74,16 +74,19 @@ void AudioOutputStreamWrapper::do_wrap(const v8::Local<v8::Object> &obj) {
if(this->_own_handle) {
this->call_underflow = Nan::async_callback([&]{
Nan::HandleScope scope;
auto handle = this->handle();
auto callback = Nan::Get(handle, Nan::New<v8::String>("callback_underflow").ToLocalChecked()).ToLocalChecked();
if(callback->IsFunction())
callback.As<v8::Function>()->Call(Nan::Undefined(), 0, nullptr);
callback.As<v8::Function>()->Call(Nan::GetCurrentContext(), Nan::Undefined(), 0, nullptr);
});
this->call_overflow = Nan::async_callback([&]{
Nan::HandleScope scope;
auto handle = this->handle();
auto callback = Nan::Get(handle, Nan::New<v8::String>("callback_overflow").ToLocalChecked()).ToLocalChecked();
if(callback->IsFunction())
callback.As<v8::Function>()->Call(Nan::Undefined(), 0, nullptr);
callback.As<v8::Function>()->Call(Nan::GetCurrentContext(), Nan::Undefined(), 0, nullptr);
});
this->_own_handle->on_overflow = [&](size_t){ this->call_overflow(); };
@ -151,7 +154,7 @@ NAN_METHOD(AudioOutputStreamWrapper::_write_data) {
return;
}
auto interleaved = info[1]->BooleanValue();
auto interleaved = info[1]->BooleanValue(info.GetIsolate());
auto js_buffer = info[0].As<v8::ArrayBuffer>()->GetContents();
if(js_buffer.ByteLength() % (handle->channel_count * 4) != 0) {
@ -177,8 +180,8 @@ NAN_METHOD(AudioOutputStreamWrapper::_write_data_rated) {
return;
}
auto sample_rate = info[2]->NumberValue();
auto interleaved = info[1]->BooleanValue();
auto sample_rate = info[2]->NumberValue(Nan::GetCurrentContext()).FromMaybe(0);
auto interleaved = info[1]->BooleanValue(info.GetIsolate());
auto js_buffer = info[0].As<v8::ArrayBuffer>()->GetContents();
auto samples = js_buffer.ByteLength() / handle->channel_count / 4;
@ -249,7 +252,7 @@ NAN_METHOD(AudioOutputStreamWrapper::_set_buffer_latency) {
return;
}
handle->min_buffer = (size_t) ceil(handle->sample_rate * info[0]->NumberValue());
handle->min_buffer = (size_t) ceil(handle->sample_rate * info[0]->NumberValue(Nan::GetCurrentContext()).FromMaybe(0));
}
NAN_METHOD(AudioOutputStreamWrapper::_get_buffer_max_latency) {
@ -278,5 +281,5 @@ NAN_METHOD(AudioOutputStreamWrapper::_set_buffer_max_latency) {
return;
}
handle->max_latency = (size_t) ceil(handle->sample_rate * info[0]->NumberValue());
handle->max_latency = (size_t) ceil(handle->sample_rate * info[0]->NumberValue(Nan::GetCurrentContext()).FromMaybe(0));
}

View File

@ -67,7 +67,7 @@ NAN_METHOD(player::set_playback_device) {
}
std::string error;
if(!global_audio_output->open_device(error, info[0]->NumberValue())) {
if(!global_audio_output->open_device(error, info[0]->NumberValue(Nan::GetCurrentContext()).FromMaybe(0))) {
Nan::ThrowError(Nan::New<v8::String>("failed to open device (" + error + ")").ToLocalChecked());
return;
}
@ -109,5 +109,5 @@ NAN_METHOD(player::set_master_volume) {
Nan::ThrowError("invalid arguments");
return;
}
global_audio_output->set_volume(info[0]->NumberValue());
global_audio_output->set_volume(info[0]->NumberValue(Nan::GetCurrentContext()).FromMaybe(0));
}

View File

@ -131,7 +131,7 @@ NAN_METHOD(AudioRecorderWrapper::_set_device) {
return;
}
auto device_id = info[0]->Int32Value();
auto device_id = info[0]->Int32Value(Nan::GetCurrentContext()).FromMaybe(0);
string error;
if(!input->open_device(error, device_id)) {
@ -201,6 +201,6 @@ NAN_METHOD(AudioRecorderWrapper::_delete_consumer) {
return;
}
auto consumer = ObjectWrap::Unwrap<AudioConsumerWrapper>(info[0]->ToObject());
auto consumer = ObjectWrap::Unwrap<AudioConsumerWrapper>(info[0]->ToObject(Nan::GetCurrentContext()).ToLocalChecked());
handle->delete_consumer(consumer);
}

View File

@ -92,12 +92,22 @@ void ServerConnection::initialize() {
this->voice_connection->_ref = this->voice_connection;
this->voice_connection->initialize_js_object();
this->execute_pending_commands = Nan::async_callback([&]{ this->_execute_callback_commands(); });
this->execute_pending_voice = Nan::async_callback([&]{ this->_execute_callback_voice(); });
this->execute_callback_disconnect = Nan::async_callback([&](std::string reason){ this->_execute_callback_disconnect(reason); });
this->execute_pending_commands = Nan::async_callback([&]{
Nan::HandleScope scope;
this->_execute_callback_commands();
});
this->execute_pending_voice = Nan::async_callback([&]{
Nan::HandleScope scope;
this->_execute_callback_voice();
});
this->execute_callback_disconnect = Nan::async_callback([&](std::string reason){
Nan::HandleScope scope;
this->_execute_callback_disconnect(reason);
});
this->call_connect_result = Nan::async_callback([&](ErrorHandler::error_id error_id) {
Nan::HandleScope scope;
/* lets update the server type */
{
auto js_this = this->handle();
@ -117,6 +127,7 @@ void ServerConnection::initialize() {
this->call_disconnect_result = Nan::async_callback([&](ErrorHandler::error_id error_id) {
Nan::HandleScope scope;
v8::Local<v8::Value> argv[1];
argv[0] = Nan::New<v8::Number>(error_id);
@ -188,7 +199,7 @@ NAN_METHOD(ServerConnection::connect) {
return;
}
v8::Local arguments = info[0]->ToObject();
v8::Local arguments = info[0]->ToObject(Nan::GetCurrentContext()).ToLocalChecked();
if(!arguments->IsObject()) {
Nan::ThrowError(tr("Invalid argument"));
@ -231,7 +242,7 @@ NAN_METHOD(ServerConnection::connect) {
this->protocol_handler->reset();
if(identity_key->IsString()) {
auto& identity = this->protocol_handler->get_identity_key();
auto key = base64::decode(*Nan::Utf8String(identity_key->ToString()));
auto key = base64::decode(*Nan::Utf8String(identity_key->ToString(Nan::GetCurrentContext()).ToLocalChecked()));
if(ecc_import((u_char*) key.data(), key.length(), &identity) != CRYPT_OK) {
Nan::ThrowError(tr("failed to import identity"));
return;
@ -256,7 +267,7 @@ NAN_METHOD(ServerConnection::connect) {
hints.ai_family = AF_UNSPEC;
auto _remote_host = Nan::Utf8String(remote_host->ToString());
auto _remote_host = Nan::Utf8String(remote_host->ToString(Nan::GetCurrentContext()).ToLocalChecked());
if(getaddrinfo(*_remote_host, nullptr, &hints, &result) != 0 || !result) {
this->call_connect_result(this->errors.register_error(tr("failed to resolve hostname")));
return;
@ -267,9 +278,9 @@ NAN_METHOD(ServerConnection::connect) {
}
switch(remote_address.ss_family) {
case AF_INET:
((sockaddr_in*) &remote_address)->sin_port = htons(remote_port->Int32Value());
((sockaddr_in*) &remote_address)->sin_port = htons(remote_port->Int32Value(Nan::GetCurrentContext()).FromMaybe(0));
case AF_INET6:
((sockaddr_in6*) &remote_address)->sin6_port = htons(remote_port->Int32Value());
((sockaddr_in6*) &remote_address)->sin6_port = htons(remote_port->Int32Value(Nan::GetCurrentContext()).FromMaybe(0));
default:break;
}
@ -283,7 +294,7 @@ NAN_METHOD(ServerConnection::connect) {
this->socket->on_data = [&](const pipes::buffer_view& buffer) { this->protocol_handler->progress_packet(buffer); };
if(teamspeak->IsBoolean() && teamspeak->BooleanValue())
if(teamspeak->IsBoolean() && teamspeak->BooleanValue(info.GetIsolate()))
this->protocol_handler->server_type = server_type::TEAMSPEAK;
this->protocol_handler->connect();
}
@ -333,7 +344,7 @@ NAN_METHOD(ServerConnection::error_message) {
return;
}
auto error = this->errors.get_message(info[0]->IntegerValue());
auto error = this->errors.get_message(info[0]->IntegerValue(Nan::GetCurrentContext()).FromMaybe(0));
info.GetReturnValue().Set(Nan::New<v8::String>(error).ToLocalChecked());
}
@ -364,7 +375,7 @@ NAN_METHOD(ServerConnection::send_command) {
}
auto begin = chrono::system_clock::now();
auto command = info[0]->ToString();
auto command = info[0]->ToString(Nan::GetCurrentContext()).ToLocalChecked();
auto arguments = info[1].As<v8::Array>();
auto switches = info[2].As<v8::Array>();
@ -376,20 +387,20 @@ NAN_METHOD(ServerConnection::send_command) {
return;
}
v8::Local<v8::Array> properties = object->ToObject()->GetOwnPropertyNames();
v8::Local<v8::Array> properties = object->ToObject(Nan::GetCurrentContext()).ToLocalChecked()->GetOwnPropertyNames(Nan::GetCurrentContext()).ToLocalChecked();
for(uint32_t i = 0; i < properties->Length(); i++) {
auto key = properties->Get(i)->ToString();
auto value = object->ToObject()->Get(key);
auto key = properties->Get(i)->ToString(Nan::GetCurrentContext()).ToLocalChecked();
auto value = object->ToObject(Nan::GetCurrentContext()).ToLocalChecked()->Get(Nan::GetCurrentContext(), key).ToLocalChecked();
string key_string = *Nan::Utf8String(key);
if(value->IsInt32())
cmd[index][key_string] = value->Int32Value();
cmd[index][key_string] = value->Int32Value(Nan::GetCurrentContext()).FromMaybe(0);
else if(value->IsNumber() || value->IsNumberObject())
cmd[index][key_string] = _to_string<double>(value->NumberValue()); /* requires our own conversation because node overrides stuff to 0,0000*/
cmd[index][key_string] = _to_string<double>(value->NumberValue(Nan::GetCurrentContext()).FromMaybe(0)); /* requires our own conversation because node overrides stuff to 0,0000*/
else if(value->IsString())
cmd[index][key_string] = *Nan::Utf8String(value->ToString());
cmd[index][key_string] = *Nan::Utf8String(value->ToString(Nan::GetCurrentContext()).ToLocalChecked());
else if(value->IsBoolean() || value->IsBooleanObject())
cmd[index][key_string] = value->BooleanValue();
cmd[index][key_string] = value->BooleanValue(info.GetIsolate());
else if(value->IsNullOrUndefined())
cmd[index][key_string] = "";
else {
@ -442,7 +453,7 @@ NAN_METHOD(ServerConnection::send_voice_data) {
auto voice_data = info[0].As<v8::Uint8Array>()->Buffer();
this->send_voice_data(voice_data->GetContents().Data(), voice_data->GetContents().ByteLength(), (uint8_t) info[1]->Int32Value(), info[2]->BooleanValue());
this->send_voice_data(voice_data->GetContents().Data(), voice_data->GetContents().ByteLength(), (uint8_t) info[1]->Int32Value(Nan::GetCurrentContext()).FromMaybe(0), info[2]->BooleanValue(info.GetIsolate()));
}
@ -463,9 +474,9 @@ NAN_METHOD(ServerConnection::send_voice_data_raw) {
return;
}
auto channels = info[1]->Int32Value();
auto sample_rate = info[2]->Int32Value();
auto flag_head = info[2]->BooleanValue();
auto channels = info[1]->Int32Value(Nan::GetCurrentContext()).FromMaybe(0);
auto sample_rate = info[2]->Int32Value(Nan::GetCurrentContext()).FromMaybe(0);
auto flag_head = info[2]->BooleanValue(info.GetIsolate());
auto voice_data = info[0].As<v8::Float32Array>()->Buffer();
auto vs = this->voice_connection->voice_sender();
@ -488,6 +499,7 @@ void ServerConnection::send_voice_data(const void *buffer, size_t buffer_length,
if(head) /* head packet */
packet->enable_flag(ts::protocol::PacketFlag::Compressed);
#define FUZZ_VOICE
#ifdef FUZZ_VOICE
if((rand() % 10) < 2) {
log_info(category::connection, tr("Dropping voice packet"));
@ -572,7 +584,7 @@ void ServerConnection::_execute_callback_commands() {
}
arguments[2] = switched;
callback->Call(Nan::Undefined(), 3, arguments);
callback->Call(Nan::GetCurrentContext(), Nan::Undefined(), 3, arguments);
}
}
@ -614,7 +626,7 @@ void ServerConnection::_execute_callback_voice() {
arguments[2] = Nan::New<v8::Integer>(next_packet->codec_id);
arguments[3] = Nan::New<v8::Boolean>(next_packet->flag_head);
arguments[4] = Nan::New<v8::Integer>(next_packet->packet_id);
callback->Call(Nan::Undefined(), 5, arguments);
callback->Call(Nan::GetCurrentContext(), Nan::Undefined(), 5, arguments);
}
}
@ -627,6 +639,6 @@ void ServerConnection::_execute_callback_disconnect(const std::string &reason) {
v8::Local<v8::Value> arguments[1];
arguments[0] = Nan::New<v8::String>(reason).ToLocalChecked();
callback->Call(Nan::Undefined(), 1, arguments);
callback->Call(Nan::GetCurrentContext(), Nan::Undefined(), 1, arguments);
}

View File

@ -10,6 +10,7 @@
typedef int socklen_t;
#else
#include <unistd.h>
#include <netinet/ip.h>
#endif
using namespace std;
@ -33,6 +34,13 @@ bool UDPSocket::initialize() {
return false;
}
/*
* TODO: Make configurable
*/
//uint8_t value = IPTOS_DSCP_EF;
//if(setsockopt(this->file_descriptor, IPPROTO_IP, IP_TOS, &value, sizeof(value)) < 0)
// log_warn(category::connection, "Failed to set TOS high priority on socket");
this->io_base = event_base_new();
if(!this->io_base) { /* may too many file descriptors already open */
this->finalize();

View File

@ -73,7 +73,10 @@ void VoiceClientWrap::do_wrap(const v8::Local<v8::Object> &object) {
Nan::Set(object, Nan::New<v8::String>("client_id").ToLocalChecked(), Nan::New<v8::Number>(handle->client_id()));
handle->on_state_changed = [&]{ this->call_state_changed(); };
this->call_state_changed = Nan::async_callback([&]{ this->_call_state_changed(); });
this->call_state_changed = Nan::async_callback([&]{
Nan::HandleScope scope;
this->_call_state_changed();
});
}
void VoiceClientWrap::_call_state_changed() {
@ -95,12 +98,12 @@ void VoiceClientWrap::_call_state_changed() {
if(call_playback_callback) {
auto callback = Nan::Get(this->handle(), Nan::New<v8::String>("callback_playback").ToLocalChecked()).ToLocalChecked();
if(callback->IsFunction())
callback.As<v8::Function>()->Call(Nan::Undefined(), 0, nullptr);
callback.As<v8::Function>()->Call(Nan::GetCurrentContext(), Nan::Undefined(), 0, nullptr);
}
if(call_stopped_callback) {
auto callback = Nan::Get(this->handle(), Nan::New<v8::String>("callback_stopped").ToLocalChecked()).ToLocalChecked();
if(callback->IsFunction())
callback.As<v8::Function>()->Call(Nan::Undefined(), 0, nullptr);
callback.As<v8::Function>()->Call(Nan::GetCurrentContext(), Nan::Undefined(), 0, nullptr);
}
auto callback = Nan::Get(this->handle(), Nan::New<v8::String>("callback_state_changed").ToLocalChecked()).ToLocalChecked();
@ -108,7 +111,7 @@ void VoiceClientWrap::_call_state_changed() {
v8::Local<v8::Value> argv[1] = {
Nan::New<v8::Number>(state)
};
callback.As<v8::Function>()->Call(Nan::Undefined(), 1, argv);
callback.As<v8::Function>()->Call(Nan::GetCurrentContext(), Nan::Undefined(), 1, argv);
}
}
@ -157,7 +160,7 @@ NAN_METHOD(VoiceClientWrap::_set_volume) {
return;
}
handle->set_volume(info[0]->NumberValue());
handle->set_volume(info[0]->NumberValue(Nan::GetCurrentContext()).FromMaybe(0));
}
NAN_METHOD(VoiceClientWrap::_abort_replay) {
auto client = ObjectWrap::Unwrap<VoiceClientWrap>(info.Holder());

View File

@ -61,7 +61,7 @@ NAN_METHOD(VoiceConnectionWrap::_encoding_supported) {
Nan::ThrowError("invalid argument count");
return;
}
auto codec = info[0]->Uint32Value();
auto codec = info[0]->Uint32Value(Nan::GetCurrentContext()).FromMaybe(0);
info.GetReturnValue().Set(codec >= 4 && codec <= 5); /* ignore SPEX currently :/ */
}
@ -71,7 +71,7 @@ NAN_METHOD(VoiceConnectionWrap::_decoding_supported) {
Nan::ThrowError("invalid argument count");
return;
}
auto codec = info[0]->Uint32Value();
auto codec = info[0]->Uint32Value(Nan::GetCurrentContext()).FromMaybe(0);
info.GetReturnValue().Set(codec >= 4 && codec <= 5); /* ignore SPEX currently :/ */
}
@ -85,7 +85,7 @@ NAN_METHOD(VoiceConnectionWrap::register_client) {
Nan::ThrowError("invalid argument count");
return;
}
auto id = info[0]->Uint32Value();
auto id = info[0]->Uint32Value(Nan::GetCurrentContext()).FromMaybe(0);
auto handle = this->handle.lock();
if(!handle) {
Nan::ThrowError("handle has been deallocated");
@ -131,7 +131,7 @@ NAN_METHOD(VoiceConnectionWrap::unregister_client) {
Nan::ThrowError("invalid argument count");
return;
}
auto id = info[0]->Uint32Value();
auto id = info[0]->Uint32Value(Nan::GetCurrentContext()).FromMaybe(0);
auto handle = this->handle.lock();
if(!handle) {
Nan::ThrowError("handle has been deallocated");
@ -180,8 +180,8 @@ NAN_METHOD(VoiceConnectionWrap::set_audio_source) {
this->release_recorder();
if(!info[0]->IsNullOrUndefined()) {
this->_voice_recoder_ptr = ObjectWrap::Unwrap<audio::recorder::AudioConsumerWrapper>(info[0]->ToObject());
this->_voice_recoder_handle.Reset(info[0]->ToObject());
this->_voice_recoder_ptr = ObjectWrap::Unwrap<audio::recorder::AudioConsumerWrapper>(info[0]->ToObject(Nan::GetCurrentContext()).ToLocalChecked());
this->_voice_recoder_handle.Reset(info[0]->ToObject(Nan::GetCurrentContext()).ToLocalChecked());
auto native_consumer = this->_voice_recoder_ptr->native_consumer();

View File

@ -7,6 +7,7 @@
#ifndef WIN32
#include <unistd.h>
#include <misc/net.h>
#else
#include <ws2tcpip.h>
#define SOCK_NONBLOCK (0)
@ -546,6 +547,7 @@ void FileTransferManager::remove_transfer(tc::ft::Transfer *transfer) {
}
#ifdef NODEJS_API
NAN_MODULE_INIT(JSTransfer::Init) {
auto klass = Nan::New<v8::FunctionTemplate>(JSTransfer::NewInstance);
klass->SetClassName(Nan::New("JSTransfer").ToLocalChecked());
@ -569,7 +571,7 @@ NAN_METHOD(JSTransfer::NewInstance) {
* server_transfer_id: number;
* object: HandledTransferObject;
*/
auto options = info[0]->ToObject();
auto options = info[0]->ToObject(Nan::GetCurrentContext()).ToLocalChecked();
v8::Local<v8::String> key = options->Get(Nan::New<v8::String>("transfer_key").ToLocalChecked()).As<v8::String>();
v8::Local<v8::Number> client_transfer_id = options->Get(Nan::New<v8::String>("client_transfer_id").ToLocalChecked()).As<v8::Number>();
v8::Local<v8::Number> server_transfer_id = options->Get(Nan::New<v8::String>("server_transfer_id").ToLocalChecked()).As<v8::Number>();
@ -598,10 +600,10 @@ NAN_METHOD(JSTransfer::NewInstance) {
auto t_options = make_unique<TransferOptions>();
t_options->transfer_key = *Nan::Utf8String(key);
t_options->client_transfer_id = client_transfer_id->Int32Value();
t_options->server_transfer_id = server_transfer_id->Int32Value();
t_options->client_transfer_id = client_transfer_id->Int32Value(Nan::GetCurrentContext()).FromMaybe(0);
t_options->server_transfer_id = server_transfer_id->Int32Value(Nan::GetCurrentContext()).FromMaybe(0);
t_options->remote_address = *Nan::Utf8String(remote_address);
t_options->remote_port = remote_port->Int32Value();
t_options->remote_port = remote_port->Int32Value(Nan::GetCurrentContext()).FromMaybe(0);
string error;
auto transfer = transfer_manager->register_transfer(error, transfer_object, move(t_options));
@ -635,10 +637,22 @@ NAN_METHOD(JSTransfer::NewInstance) {
}
JSTransfer::JSTransfer(std::shared_ptr<tc::ft::Transfer> transfer) : _transfer(move(transfer)) {
this->call_failed = Nan::async_callback([&](std::string error) { this->callback_failed(error); });
this->call_finished = Nan::async_callback([&](bool f) { this->callback_finished(f); });
this->call_start = Nan::async_callback([&] { this->callback_start(); });
this->call_progress = Nan::async_callback([&](uint64_t a, uint64_t b) { this->callback_progress(a, b); });
this->call_failed = Nan::async_callback([&](std::string error) {
Nan::HandleScope scope;
this->callback_failed(error);
});
this->call_finished = Nan::async_callback([&](bool f) {
Nan::HandleScope scope;
this->callback_finished(f);
});
this->call_start = Nan::async_callback([&] {
Nan::HandleScope scope;
this->callback_start();
});
this->call_progress = Nan::async_callback([&](uint64_t a, uint64_t b) {
Nan::HandleScope scope;
this->callback_progress(a, b);
});
this->_transfer->callback_failed = [&](std::string error) { this->call_failed(std::forward<string>(error)); };
this->_transfer->callback_finished = [&](bool f) { this->call_finished(std::forward<bool>(f)); };
@ -689,7 +703,7 @@ void JSTransfer::callback_finished(bool flag) {
v8::Local<v8::Value> arguments[1];
arguments[0] = Nan::New<v8::Boolean>(flag);
callback->Call(Nan::Undefined(), 1, arguments);
callback->Call(Nan::GetCurrentContext(), Nan::Undefined(), 1, arguments);
}
void JSTransfer::callback_start() {
@ -697,7 +711,7 @@ void JSTransfer::callback_start() {
if(callback.IsEmpty() || !callback->IsFunction())
return;
callback->Call(Nan::Undefined(), 0, nullptr);
callback->Call(Nan::GetCurrentContext(), Nan::Undefined(), 0, nullptr);
}
void JSTransfer::callback_progress(uint64_t a, uint64_t b) {
@ -708,7 +722,7 @@ void JSTransfer::callback_progress(uint64_t a, uint64_t b) {
v8::Local<v8::Value> arguments[2];
arguments[0] = Nan::New<v8::Number>(a);
arguments[1] = Nan::New<v8::Number>(b);
callback->Call(Nan::Undefined(), 2, arguments);
callback->Call(Nan::GetCurrentContext(), Nan::Undefined(), 2, arguments);
}
void JSTransfer::callback_failed(std::string error) {
@ -722,6 +736,6 @@ void JSTransfer::callback_failed(std::string error) {
v8::Local<v8::Value> arguments[1];
arguments[0] = Nan::New<v8::String>(error).ToLocalChecked();
callback->Call(Nan::Undefined(), 1, arguments);
callback->Call(Nan::GetCurrentContext(), Nan::Undefined(), 1, arguments);
}
#endif

View File

@ -54,6 +54,8 @@ inline v8::Local<v8::Value> get_logger_method() {
void logger::initialize_node() {
log_messages_callback = Nan::async_callback([]{
Nan::HandleScope scope;
auto isolate = Nan::GetCurrentContext()->GetIsolate();
v8::Local<v8::Value> logger_method = get_logger_method();
@ -74,7 +76,7 @@ void logger::initialize_node() {
arguments[1] = Nan::New<v8::Number>(entry->level);
arguments[2] = v8::String::NewExternalOneByte(isolate, new StdExternalStringResourceBase(entry->message)).ToLocalChecked();
logger_method.As<v8::Function>()->Call(Nan::Undefined(), 3, arguments);
logger_method.As<v8::Function>()->Call(Nan::GetCurrentContext(), Nan::Undefined(), 3, arguments);
} else {
std::cout << "Failed to log message! Invalid method!" << std::endl;
}

View File

@ -3,7 +3,11 @@ module.paths.push("../../build/linux_x64");
module.paths.push("../../build/win32_64");
import * as fs from "fs";
const original_require = require;
require = module => original_require("/home/wolverindev/TeaSpeak-Client/client/native/build/linux_x64/" + module + ".node");
import * as handle from "teaclient_connection";
require = original_require;
const connection_list = [];
const connection = handle.spawn_server_connection();
@ -13,8 +17,8 @@ console.dir(handle);
console.log("Query devices...");
console.log("Devices: %o", handle.audio.available_devices());
console.log("Current playback device: %o", handle.audio.playback.current_device());
handle.audio.playback.set_device(15);
console.log("Current playback device: %o", handle.audio.playback.current_device());
//handle.audio.playback.set_device(14);
//console.log("Current playback device: %o", handle.audio.playback.current_device());
const stream = handle.audio.playback.create_stream();
console.log("Own stream: %o", stream);
@ -24,7 +28,17 @@ console.log("Own stream: %o", stream);
const recorder = handle.audio.record.create_recorder();
console.log("Have device: %o", recorder);
console.log("Device: %o", recorder.get_device());
recorder.set_device(15);
if(recorder.get_device() == -1) {
console.log("Looking for devices");
for(const device of handle.audio.available_devices()) {
if(!device.input_supported)
continue;
if(device.name != "pulse")
continue;
console.log("Found pulse at %o", device.device_index);
recorder.set_device(device.device_index);
}
}
console.log("Device: %o", recorder.get_device());
recorder.start();
console.log("Started: %o", recorder.started());