2019-10-26 01:51:40 +02:00
|
|
|
#include <v8.h>
|
|
|
|
#include <nan.h>
|
|
|
|
#include <node.h>
|
|
|
|
#include <iostream>
|
|
|
|
#include <mutex>
|
|
|
|
#include <event2/thread.h>
|
|
|
|
#include <misc/digest.h>
|
2020-02-08 16:50:48 +01:00
|
|
|
#include <NanStrings.h>
|
2019-10-26 01:51:40 +02:00
|
|
|
|
|
|
|
#include "logger.h"
|
2019-11-24 18:38:50 +01:00
|
|
|
#include "include/NanException.h"
|
|
|
|
#include "include/NanEventCallback.h"
|
2019-10-26 01:51:40 +02:00
|
|
|
#include "connection/ServerConnection.h"
|
|
|
|
#include "connection/audio/VoiceConnection.h"
|
|
|
|
#include "connection/audio/VoiceClient.h"
|
|
|
|
#include "connection/ft/FileTransferManager.h"
|
|
|
|
#include "connection/ft/FileTransferObject.h"
|
|
|
|
#include "audio/AudioOutput.h"
|
2020-02-08 16:50:48 +01:00
|
|
|
#include "audio/driver/AudioDriver.h"
|
2019-10-26 01:51:40 +02:00
|
|
|
#include "audio/js/AudioOutputStream.h"
|
|
|
|
#include "audio/js/AudioPlayer.h"
|
|
|
|
#include "audio/js/AudioRecorder.h"
|
|
|
|
#include "audio/js/AudioConsumer.h"
|
|
|
|
#include "audio/js/AudioFilter.h"
|
2020-03-18 23:32:57 +01:00
|
|
|
#include "audio/AudioEventLoop.h"
|
|
|
|
#include "audio/sounds/SoundPlayer.h"
|
2019-10-26 01:51:40 +02:00
|
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern "C" {
|
|
|
|
#include <tomcrypt_misc.h>
|
|
|
|
#include <tomcrypt.h>
|
|
|
|
|
|
|
|
#include <tommath.h>
|
|
|
|
};
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
using namespace tc;
|
|
|
|
using namespace tc::connection;
|
|
|
|
using namespace tc::ft;
|
|
|
|
|
|
|
|
void testTomMath(){
|
|
|
|
mp_int x{};
|
|
|
|
mp_init(&x);
|
|
|
|
mp_read_radix(&x, "2280880776330203449294339386427307168808659578661428574166839717243346815923951250209099128371839254311904649344289668000305972691071196233379180504231889", 10);
|
|
|
|
|
|
|
|
mp_int n{};
|
|
|
|
mp_init(&n);
|
|
|
|
mp_read_radix(&n, "436860662135489324843442078840868871476482593772359054106809367217662215065650065606351911592188139644751920724885335056877706082800496073391354240530016", 10);
|
|
|
|
|
|
|
|
mp_int exp{};
|
|
|
|
mp_init(&exp);
|
|
|
|
mp_2expt(&exp, 1000);
|
|
|
|
|
|
|
|
|
|
|
|
mp_int r{};
|
|
|
|
mp_init(&r);
|
|
|
|
|
|
|
|
if(mp_exptmod(&x, &exp, &n, &r) == CRYPT_OK) {
|
|
|
|
log_warn(category::general, tr("TomCrypt check failed. Server connects main fail due to this mistake!"));
|
|
|
|
//Nan::ThrowError("Tomcrypt library is too modern. Use an oder one!");
|
|
|
|
//return;
|
|
|
|
}
|
|
|
|
//assert(mp_exptmod(&x, &exp, &n, &r) != CRYPT_OK); //if this method succeed than tommath failed. Unknown why but it is so
|
|
|
|
|
|
|
|
mp_clear_multi(&x, &n, &exp, &r, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
tc::audio::AudioOutput* global_audio_output;
|
|
|
|
#define ENUM_SET(object, key, value) \
|
2020-03-18 23:32:57 +01:00
|
|
|
Nan::DefineOwnProperty(object, Nan::New<v8::String>(key).ToLocalChecked(), Nan::New<v8::Number>((uint32_t) value), v8::DontDelete); \
|
|
|
|
Nan::Set(object, (uint32_t) value, Nan::New<v8::String>(key).ToLocalChecked());
|
2019-10-26 01:51:40 +02:00
|
|
|
|
|
|
|
NAN_MODULE_INIT(init) {
|
|
|
|
logger::initialize_node();
|
|
|
|
#ifndef WIN32
|
|
|
|
logger::info(category::general, tr("Hello World from C. PPID: {}, PID: {}"), getppid(), getpid());
|
|
|
|
#else
|
|
|
|
logger::info(category::general, tr("Hello World from C. PID: {}"), _getpid());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
{
|
|
|
|
auto data = (uint8_t*) "Hello World";
|
|
|
|
auto hash_result = digest::sha1((const char*) data, 11);
|
|
|
|
if(hash_result.length() != 20)
|
|
|
|
Nan::ThrowError("digest::sha1 test failed");
|
|
|
|
log_error(category::connection, tr("Hash result: {}"), hash_result.length());
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
auto data = (uint8_t*) "Hello World";
|
|
|
|
auto hash_result = digest::sha1(std::string("Hello World"));
|
|
|
|
if(hash_result.length() != 20)
|
|
|
|
Nan::ThrowError("digest::sha1 test failed");
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto data = (uint8_t*) "Hello World";
|
|
|
|
|
|
|
|
uint8_t result[SHA_DIGEST_LENGTH];
|
|
|
|
digest::tomcrypt::sha1((char*) data, 11, result);
|
|
|
|
auto hash_result = std::string((const char*) result, SHA_DIGEST_LENGTH);
|
|
|
|
log_error(category::connection, tr("Hash result: {}"), hash_result.length());
|
|
|
|
}
|
|
|
|
|
|
|
|
string error;
|
2020-02-08 16:50:48 +01:00
|
|
|
tc::audio::initialize(); //TODO: Notify JS when initialized?
|
2019-10-26 01:51:40 +02:00
|
|
|
|
|
|
|
logger::info(category::general, "Loading crypt modules");
|
|
|
|
std::string descriptors = "LTGE";
|
|
|
|
{
|
|
|
|
int crypt_init = false;
|
|
|
|
for(const auto& c : descriptors)
|
|
|
|
if((crypt_init = crypt_mp_init(&c) == CRYPT_OK))
|
|
|
|
break;
|
|
|
|
if(!crypt_init) {
|
|
|
|
Nan::ThrowError("failed to init tomcrypt");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if(register_prng(&sprng_desc) == -1) {
|
|
|
|
Nan::ThrowError("could not setup prng");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (register_cipher(&rijndael_desc) == -1) {
|
|
|
|
Nan::ThrowError("could not setup rijndael");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
testTomMath();
|
|
|
|
}
|
|
|
|
logger::info(category::general, "Crypt modules loaded");
|
|
|
|
|
|
|
|
#ifdef WIN32
|
|
|
|
evthread_use_windows_threads();
|
|
|
|
#else
|
|
|
|
evthread_use_pthreads();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
tc::audio::init_event_loops();
|
2020-02-08 16:50:48 +01:00
|
|
|
tc::audio::initialize([]{
|
|
|
|
std::string error{};
|
|
|
|
|
|
|
|
std::shared_ptr<tc::audio::AudioDevice> default_output{};
|
|
|
|
for(auto& device : tc::audio::devices()) {
|
|
|
|
if(device->is_output_default()) {
|
|
|
|
default_output = device;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: Test error codes and make the audi playback device configurable */
|
2020-02-13 22:16:34 +01:00
|
|
|
global_audio_output = new tc::audio::AudioOutput(2, 44100);
|
2020-02-08 16:50:48 +01:00
|
|
|
global_audio_output->set_device(default_output);
|
|
|
|
if(!global_audio_output->playback(error)) {
|
|
|
|
logger::error(category::audio, "Failed to start audio playback: {}", error);
|
|
|
|
}
|
|
|
|
});
|
2019-10-26 01:51:40 +02:00
|
|
|
|
|
|
|
{
|
|
|
|
auto namespace_audio = Nan::New<v8::Object>();
|
2020-02-08 16:50:48 +01:00
|
|
|
Nan::Set(namespace_audio, Nan::LocalString("available_devices"), Nan::GetFunction(Nan::New<v8::FunctionTemplate>(audio::available_devices)).ToLocalChecked());
|
|
|
|
Nan::Set(namespace_audio, Nan::LocalString("initialize"), Nan::GetFunction(Nan::New<v8::FunctionTemplate>(audio::await_initialized_js)).ToLocalChecked());
|
|
|
|
Nan::Set(namespace_audio, Nan::LocalString("initialized"), Nan::GetFunction(Nan::New<v8::FunctionTemplate>(audio::initialized_js)).ToLocalChecked());
|
|
|
|
|
|
|
|
{
|
2019-10-26 01:51:40 +02:00
|
|
|
auto namespace_playback = Nan::New<v8::Object>();
|
|
|
|
audio::player::init_js(namespace_playback);
|
|
|
|
audio::AudioOutputStreamWrapper::Init(namespace_playback);
|
|
|
|
Nan::Set(namespace_audio, Nan::New<v8::String>("playback").ToLocalChecked(), namespace_playback);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto namespace_record = Nan::New<v8::Object>();
|
|
|
|
audio::recorder::init_js(namespace_record);
|
|
|
|
audio::recorder::AudioRecorderWrapper::Init(namespace_record);
|
|
|
|
audio::recorder::AudioConsumerWrapper::Init(namespace_record);
|
|
|
|
audio::recorder::AudioFilterWrapper::Init(namespace_record);
|
|
|
|
Nan::Set(namespace_audio, Nan::New<v8::String>("record").ToLocalChecked(), namespace_record);
|
|
|
|
}
|
2020-03-18 23:32:57 +01:00
|
|
|
{
|
|
|
|
auto namespace_sounds = Nan::New<v8::Object>();
|
|
|
|
Nan::Set(namespace_sounds, Nan::LocalString("playback_sound"), Nan::GetFunction(Nan::New<v8::FunctionTemplate>(audio::sounds::playback_sound_js)).ToLocalChecked());
|
|
|
|
Nan::Set(namespace_sounds, Nan::LocalString("cancel_playback"), Nan::GetFunction(Nan::New<v8::FunctionTemplate>(audio::sounds::cancel_playback_js)).ToLocalChecked());
|
|
|
|
|
|
|
|
{
|
|
|
|
auto enum_object = Nan::New<v8::Object>();
|
|
|
|
ENUM_SET(enum_object, "SUCCEEDED", audio::sounds::PlaybackResult::SUCCEEDED);
|
|
|
|
ENUM_SET(enum_object, "CANCELED", audio::sounds::PlaybackResult::CANCELED);
|
|
|
|
ENUM_SET(enum_object, "SOUND_NOT_INITIALIZED", audio::sounds::PlaybackResult::SOUND_NOT_INITIALIZED);
|
|
|
|
ENUM_SET(enum_object, "FILE_OPEN_ERROR", audio::sounds::PlaybackResult::FILE_OPEN_ERROR);
|
|
|
|
ENUM_SET(enum_object, "PLAYBACK_ERROR", audio::sounds::PlaybackResult::PLAYBACK_ERROR);
|
|
|
|
|
|
|
|
Nan::DefineOwnProperty(namespace_sounds, Nan::New<v8::String>("PlaybackResult").ToLocalChecked(), enum_object, v8::DontDelete);
|
|
|
|
}
|
|
|
|
|
|
|
|
Nan::Set(namespace_audio, Nan::New<v8::String>("sounds").ToLocalChecked(), namespace_sounds);
|
|
|
|
}
|
2019-10-26 01:51:40 +02:00
|
|
|
Nan::Set(target, Nan::New<v8::String>("audio").ToLocalChecked(), namespace_audio);
|
|
|
|
}
|
|
|
|
|
|
|
|
VoiceClientWrap::Init(target);
|
|
|
|
VoiceConnectionWrap::Init(target);
|
|
|
|
{
|
|
|
|
auto enum_object = Nan::New<v8::Object>();
|
|
|
|
ENUM_SET(enum_object, "BUFFERING", tc::connection::VoiceClient::state::buffering);
|
|
|
|
ENUM_SET(enum_object, "PLAYING", tc::connection::VoiceClient::state::playing);
|
|
|
|
ENUM_SET(enum_object, "STOPPING", tc::connection::VoiceClient::state::stopping);
|
|
|
|
ENUM_SET(enum_object, "STOPPED", tc::connection::VoiceClient::state::stopped);
|
|
|
|
Nan::DefineOwnProperty(target, Nan::New<v8::String>("PlayerState").ToLocalChecked(), enum_object, v8::DontDelete);
|
|
|
|
}
|
|
|
|
|
|
|
|
transfer_manager = new tc::ft::FileTransferManager();
|
|
|
|
transfer_manager->initialize();
|
|
|
|
|
|
|
|
ServerConnection::Init(target);
|
|
|
|
Nan::Set(target, Nan::New<v8::String>("spawn_server_connection").ToLocalChecked(), Nan::GetFunction(Nan::New<v8::FunctionTemplate>(ServerConnection::new_instance)).ToLocalChecked());
|
|
|
|
|
|
|
|
/* ft namespace */
|
|
|
|
{
|
|
|
|
auto ft_namespace = Nan::New<v8::Object>();
|
|
|
|
|
|
|
|
TransferObjectWrap::Init(ft_namespace);
|
|
|
|
Nan::Set(ft_namespace,
|
|
|
|
Nan::New<v8::String>("upload_transfer_object_from_buffer").ToLocalChecked(),
|
|
|
|
Nan::GetFunction(Nan::New<v8::FunctionTemplate>(TransferJSBufferSource::create_from_buffer)).ToLocalChecked()
|
|
|
|
);
|
|
|
|
Nan::Set(ft_namespace,
|
|
|
|
Nan::New<v8::String>("download_transfer_object_from_buffer").ToLocalChecked(),
|
|
|
|
Nan::GetFunction(Nan::New<v8::FunctionTemplate>(TransferJSBufferTarget::create_from_buffer)).ToLocalChecked()
|
|
|
|
);
|
2020-06-11 13:50:37 +02:00
|
|
|
Nan::Set(ft_namespace,
|
|
|
|
Nan::New<v8::String>("upload_transfer_object_from_file").ToLocalChecked(),
|
|
|
|
Nan::GetFunction(Nan::New<v8::FunctionTemplate>(TransferFileSource::create)).ToLocalChecked()
|
|
|
|
);
|
|
|
|
Nan::Set(ft_namespace,
|
|
|
|
Nan::New<v8::String>("download_transfer_object_from_file").ToLocalChecked(),
|
|
|
|
Nan::GetFunction(Nan::New<v8::FunctionTemplate>(TransferFileTarget::create)).ToLocalChecked()
|
|
|
|
);
|
2019-10-26 01:51:40 +02:00
|
|
|
|
|
|
|
//spawn_file_connection destroy_file_connection
|
|
|
|
JSTransfer::Init(ft_namespace);
|
|
|
|
Nan::Set(ft_namespace, Nan::New<v8::String>("spawn_connection").ToLocalChecked(), Nan::GetFunction(Nan::New<v8::FunctionTemplate>(JSTransfer::NewInstance)).ToLocalChecked());
|
|
|
|
Nan::Set(ft_namespace, Nan::New<v8::String>("destroy_connection").ToLocalChecked(), Nan::GetFunction(Nan::New<v8::FunctionTemplate>(JSTransfer::destory_transfer)).ToLocalChecked());
|
|
|
|
|
|
|
|
Nan::Set(target, Nan::New<v8::String>("ft").ToLocalChecked(), ft_namespace);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* setup server types */
|
|
|
|
{
|
|
|
|
auto enum_object = Nan::New<v8::Object>();
|
|
|
|
ENUM_SET(enum_object, "UNKNOWN", tc::connection::server_type::UNKNOWN);
|
|
|
|
ENUM_SET(enum_object, "TEASPEAK", tc::connection::server_type::TEASPEAK);
|
|
|
|
ENUM_SET(enum_object, "TEAMSPEAK", tc::connection::server_type::TEAMSPEAK);
|
|
|
|
Nan::DefineOwnProperty(target, Nan::New<v8::String>("ServerType").ToLocalChecked(), enum_object, v8::DontDelete);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NODE_MODULE(MODULE_NAME, init)
|