diff --git a/bugs b/bugs index 345a464..1ef39e9 100644 --- a/bugs +++ b/bugs @@ -16,4 +16,9 @@ General: Tasks designer: TeaCup steam animated Client redesign dark [+ Chat system] - Redesign loading animation (Web) \ No newline at end of file + Redesign loading animation (Web) + + + +Notice: +electron-package-manager must be at 8.7.2 (Node 6 support)! \ No newline at end of file diff --git a/modules/crash_handler/index.ts b/modules/crash_handler/index.ts index 1aa2cd9..8c69744 100644 --- a/modules/crash_handler/index.ts +++ b/modules/crash_handler/index.ts @@ -84,11 +84,15 @@ export const handler = require( "teaclient_crash_handler"); export function initialize_handler(component_name: string, requires_file: boolean) { const start_path = requires_file ? (" " + path.join(__dirname, "..", "..")) : ""; + const success_arguments = process.argv[0] + start_path + " crash-handler success=1 dump_path=%crash_path%"; + const error_arguments = process.argv[0] + start_path + " crash-handler success=0 error=%error_message%"; + + console.log("Setting up crash handler. Success callback: %s; Error callback: %s", success_arguments, error_arguments); handler.setup_crash_handler( component_name, path.join((remote || electron).app.getPath('userData'), "crash_dumps"), - process.argv[0] + start_path + " crash-handler success=1 dump_path=%crash_path%", - process.argv[0] + start_path + " crash-handler success=0 error=%error_message%" + success_arguments, + error_arguments ); } diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt index 8ea0f78..c914766 100644 --- a/native/CMakeLists.txt +++ b/native/CMakeLists.txt @@ -57,7 +57,6 @@ function(setup_nodejs) ) target_include_directories(${NAME} PUBLIC ${NODEJS_INCLUDE_DIRS}) set_target_properties(${NAME} PROPERTIES CXX_STANDARD 17) #Needs to be overridden after _add_nodejs_module sets it to 11 - message("Add lib: ${NODEJS_LIBRARIES}") if(MSVC) add_custom_command(TARGET ${NAME} POST_BUILD diff --git a/native/crash_handler/test/test_crash/crash_dump_test_381fc65c-2a4a-46d9-e59385b6-64cd1080.dmp b/native/crash_handler/test/test_crash/crash_dump_test_381fc65c-2a4a-46d9-e59385b6-64cd1080.dmp new file mode 100644 index 0000000..ef7a41c Binary files /dev/null and b/native/crash_handler/test/test_crash/crash_dump_test_381fc65c-2a4a-46d9-e59385b6-64cd1080.dmp differ diff --git a/native/serverconnection/CMakeLists.txt b/native/serverconnection/CMakeLists.txt index daae3c4..e7fc6b9 100644 --- a/native/serverconnection/CMakeLists.txt +++ b/native/serverconnection/CMakeLists.txt @@ -83,8 +83,9 @@ include_directories(${DataPipes_INCLUDE_DIR}) find_package(Libevent REQUIRED) include_directories(${LIBEVENT_INCLUDE_DIRS}) +message("libevent include dir: ${LIBEVENT_INCLUDE_DIRS}") +message("libevent static libraries: ${LIBEVENT_STATIC_LIBRARIES}") -message(${TeaSpeak_SharedLib_ROOT_DIR}) find_package(TeaSpeak_SharedLib REQUIRED) include_directories(${TeaSpeak_SharedLib_INCLUDE_DIR}) @@ -139,6 +140,7 @@ if (WIN32) set(REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} "Ws2_32.Lib") else() set(REQUIRED_LIBRARIES ${REQUIRED_LIBRARIES} + libstdc++fs.a asound jack pthread @@ -150,4 +152,8 @@ target_link_libraries(${MODULE_NAME} ${REQUIRED_LIBRARIES}) target_compile_definitions(${MODULE_NAME} PUBLIC -DNODEJS_API) add_executable(Audio-Test ${SOURCE_FILES} test/audio/main.cpp) -target_link_libraries(Audio-Test ${REQUIRED_LIBRARIES}) \ No newline at end of file +target_link_libraries(Audio-Test ${REQUIRED_LIBRARIES}) + +#U SHA512_Final +#U SHA512_Init +#U SHA512_Update \ No newline at end of file diff --git a/native/serverconnection/src/bindings.cpp b/native/serverconnection/src/bindings.cpp index d7d5a28..dac764a 100644 --- a/native/serverconnection/src/bindings.cpp +++ b/native/serverconnection/src/bindings.cpp @@ -50,7 +50,12 @@ void testTomMath(){ mp_int r{}; mp_init(&r); - assert(mp_exptmod(&x, &exp, &n, &r) != CRYPT_OK); //if this method succeed than tommath failed. Unknown why but it is so + + if(mp_exptmod(&x, &exp, &n, &r) != CRYPT_OK) { + 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); } @@ -63,7 +68,7 @@ tc::audio::AudioOutput* global_audio_output; NAN_MODULE_INIT(init) { logger::initialize_node(); - logger::error(category::general, "Hello World from C"); + logger::info(category::general, "Hello World from C"); string error; //TODO here @@ -72,6 +77,7 @@ NAN_MODULE_INIT(init) { std::thread(audio::devices).detach(); /* cache the devices */ + logger::info(category::general, "Loading crypt modules"); std::string descriptors = "LTGE"; { int crypt_init = false; @@ -93,6 +99,7 @@ NAN_MODULE_INIT(init) { testTomMath(); } + logger::info(category::general, "Crypt modules loaded"); #ifdef WIN32 evthread_use_windows_threads(); diff --git a/native/serverconnection/src/connection/ProtocolHandler.cpp b/native/serverconnection/src/connection/ProtocolHandler.cpp index 4a14090..e05272b 100644 --- a/native/serverconnection/src/connection/ProtocolHandler.cpp +++ b/native/serverconnection/src/connection/ProtocolHandler.cpp @@ -88,13 +88,15 @@ void ProtocolHandler::execute_tick() { if(this->connection_state == connection_state::INIT_LOW || this->connection_state == connection_state::INIT_HIGH) { if(this->connect_timestamp < now - seconds(15)) { this->handle->call_connect_result.call(this->handle->errors.register_error("timeout (" + to_string(this->connection_state) + ")"), true); - this->close_connection(); + this->handle->close_connection(); + return; } } if(this->connection_state == connection_state::DISCONNECTING) { if(this->disconnect_timestamp < now - seconds(5)) { /* disconnect timeout */ - this->close_connection(); + this->handle->close_connection(); + return; } } @@ -108,7 +110,8 @@ void ProtocolHandler::execute_tick() { if(this->ping.ping_received_timestamp.time_since_epoch().count() > 0) { if(now - this->ping.ping_received_timestamp > seconds(30)) { this->handle->execute_callback_disconnect.call(tr("ping timeout"), true); - this->close_connection(); + this->handle->close_connection(); + return; } } else this->ping.ping_received_timestamp = now; @@ -504,7 +507,7 @@ void ProtocolHandler::send_acknowledge(uint16_t packet_id, bool low) { this->send_packet(packet); } -void ProtocolHandler::close_connection() { +void ProtocolHandler::do_close_connection() { this->connection_state = connection_state::DISCONNECTED; for(auto& buffer : this->_packet_buffers) { lock_guard lock(buffer.buffer_lock); diff --git a/native/serverconnection/src/connection/ProtocolHandler.h b/native/serverconnection/src/connection/ProtocolHandler.h index fcfc5ef..646a435 100644 --- a/native/serverconnection/src/connection/ProtocolHandler.h +++ b/native/serverconnection/src/connection/ProtocolHandler.h @@ -54,7 +54,7 @@ namespace tc { class ProtocolHandler { typedef ts::protocol::PacketRingBuffer packet_buffer_t; typedef std::array packet_buffers_t; - + friend class ServerConnection; public: ProtocolHandler(ServerConnection*); ~ProtocolHandler(); @@ -69,16 +69,17 @@ namespace tc { void send_packet(const std::shared_ptr& /* packet */); void send_command(const ts::Command& /* command */, const std::function & /* acknowledge callback */ = NULL); - void send_acknowledge(uint16_t /* packet id */, bool /* low */); - void disconnect(const std::string& /* message */); - void close_connection(); + + void send_acknowledge(uint16_t /* packet id */, bool /* low */); ecc_key& get_identity_key() { return this->crypto.identity; } connection_state::value connection_state = connection_state::INITIALIZING; server_type::value server_type = server_type::TEASPEAK; private: + void do_close_connection(); /* only call from ServerConnection. Close all connections via ServerConnection! */ + void handlePacketCommand(const std::shared_ptr&); void handlePacketAck(const std::shared_ptr&); void handlePacketVoice(const std::shared_ptr&); diff --git a/native/serverconnection/src/connection/ProtocolHandlerCrypto.cpp b/native/serverconnection/src/connection/ProtocolHandlerCrypto.cpp index 3d170af..b5730d3 100644 --- a/native/serverconnection/src/connection/ProtocolHandlerCrypto.cpp +++ b/native/serverconnection/src/connection/ProtocolHandlerCrypto.cpp @@ -41,14 +41,9 @@ std::string ProtocolHandler::generate_client_initiv() { if(this->server_type != server_type::TEAMSPEAK) /* if TEAMSPEAK then TS3 has been enforced */ command.enableParm("teaspeak"); /* using "old" encryption system, we expect a teaspeak=1 within the response */ { - size_t buffer_length = 265 + 5; - char buffer[265 + 5]; + size_t buffer_length = 265; + char buffer[265]; auto result = ecc_export((unsigned char *) buffer, (unsigned long*) &buffer_length, PK_PUBLIC, &this->crypto.identity); - buffer[265] = rand(); - buffer[266] = rand(); - buffer[267] = rand(); - buffer[268] = rand(); - buffer[269] = rand(); if(result == CRYPT_OK) command["omega"] = base64::encode(buffer, buffer_length); else @@ -160,8 +155,8 @@ void ProtocolHandler::handleCommandInitIVExpend2(ts::Command &cmd) { return; } - int result; - if(ecc_verify_hash((u_char*) proof.data(), proof.length(), (u_char*) crypto_hash.data(), crypto_hash.length(), &result, &server_key) != CRYPT_OK || result != 1) { + int result, crypt_result; + if((crypt_result = ecc_verify_hash((u_char*) proof.data(), proof.length(), (u_char*) crypto_hash.data(), crypto_hash.length(), &result, &server_key)) != CRYPT_OK || result != 1) { this->handle->call_connect_result.call(this->handle->errors.register_error(tr("failed to verify server integrity")), true); this->handle->close_connection(); return; diff --git a/native/serverconnection/src/connection/ServerConnection.cpp b/native/serverconnection/src/connection/ServerConnection.cpp index c6cff44..86dc0a2 100644 --- a/native/serverconnection/src/connection/ServerConnection.cpp +++ b/native/serverconnection/src/connection/ServerConnection.cpp @@ -141,6 +141,8 @@ void ServerConnection::event_loop() { auto best = this->next_tick; if(this->next_resend < best) best = this->next_resend; + if(this->event_loop_execute_connection_close) + return system_clock::time_point{}; return best; }; @@ -157,6 +159,10 @@ void ServerConnection::event_loop() { if(this->event_loop_exit) break; } + if(this->event_loop_execute_connection_close) { + this->close_connection(); + this->event_loop_execute_connection_close = false; + } auto date = chrono::system_clock::now(); if(this->next_tick <= date) { this->next_tick = date + chrono::milliseconds(500); @@ -485,10 +491,22 @@ void ServerConnection::send_voice_data(const void *buffer, size_t buffer_length, } void ServerConnection::close_connection() { + if(this_thread::get_id() == this->socket->io_thread().get_id()) { + logger::debug(category::connection, tr("close_connection() called in IO thread. Closing connection within event loop!")); + lock_guard lock(this->disconnect_lock); + if(!this->event_loop_execute_connection_close) { + this->event_loop_execute_connection_close = true; + this->event_condition.notify_one(); + } + return; + } + lock_guard lock(this->disconnect_lock); - if(this->socket) + this->event_loop_execute_connection_close = false; + if(this->socket) { this->socket->finalize(); - this->protocol_handler->close_connection(); + } + this->protocol_handler->do_close_connection(); this->socket = nullptr; this->call_disconnect_result.call(0, true); } diff --git a/native/serverconnection/src/connection/ServerConnection.h b/native/serverconnection/src/connection/ServerConnection.h index c0e1e93..543334f 100644 --- a/native/serverconnection/src/connection/ServerConnection.h +++ b/native/serverconnection/src/connection/ServerConnection.h @@ -105,6 +105,8 @@ namespace tc { bool event_loop_exit = false; /* set to true if we want to exit */ void event_loop(); + bool event_loop_execute_connection_close = false; + std::chrono::system_clock::time_point next_tick; std::chrono::system_clock::time_point next_resend; void execute_tick(); diff --git a/native/serverconnection/src/connection/Socket.cpp b/native/serverconnection/src/connection/Socket.cpp index 0fbade1..fa1bc7e 100644 --- a/native/serverconnection/src/connection/Socket.cpp +++ b/native/serverconnection/src/connection/Socket.cpp @@ -42,11 +42,11 @@ bool UDPSocket::initialize() { this->event_write = event_new(this->io_base, this->file_descriptor, EV_WRITE, &UDPSocket::_callback_write, this); event_add(this->event_read, nullptr); - this->io_thread = thread(&UDPSocket::_io_execute, this); + this->_io_thread = thread(&UDPSocket::_io_execute, this); #ifdef WIN32 //TODO set thread name #else - auto handle = this->io_thread.native_handle(); + auto handle = this->_io_thread.native_handle(); pthread_setname_np(handle, "UDPSocket loop"); #endif return true; @@ -64,7 +64,7 @@ void UDPSocket::finalize() { this->event_write = nullptr; lock.unlock(); - assert(this_thread::get_id() != this->io_thread.get_id()); + assert(this_thread::get_id() != this->_io_thread.get_id()); if(event_read) event_del_block(event_read); if(event_write) @@ -81,8 +81,8 @@ void UDPSocket::finalize() { event_base_loopexit(io_base, nullptr); } - if(this->io_thread.joinable()) - this->io_thread.join(); + if(this->_io_thread.joinable()) + this->_io_thread.join(); if(io_base) event_base_free(io_base); diff --git a/native/serverconnection/src/connection/Socket.h b/native/serverconnection/src/connection/Socket.h index 8eb8b05..605cb0b 100644 --- a/native/serverconnection/src/connection/Socket.h +++ b/native/serverconnection/src/connection/Socket.h @@ -30,6 +30,8 @@ namespace tc { void send_message(const pipes::buffer_view& /* message */); std::function on_data; + + const std::thread& io_thread() { return this->_io_thread; } private: static void _io_execute(void *_ptr_socket); static void _callback_read(evutil_socket_t, short, void*); @@ -44,7 +46,7 @@ namespace tc { int file_descriptor = 0; std::recursive_mutex io_lock; - std::thread io_thread; + std::thread _io_thread; event_base* io_base = nullptr; event* event_read = nullptr; diff --git a/package.json b/package.json index 537f3a1..074c9ce 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "test": "echo \"Error: no test specified\" && exit 1", "start": "electron --js-flags='--expose-gc' --debug --dev-tools --disable-hardware-acceleration .", "start-d": "electron . --debug -t -su http://dev.clientapi.teaspeak.de/", - "start-n": "electron . -t -su http://null.teaspeak.de/", + "start-n": "electron . -t --no-single-instance -su http://null.teaspeak.de/", "start-01": "electron . --updater-channel=test -u=http://dev.clientapi.teaspeak.de/ -d --updater-ui-loader_type=0 --updater-local-version=1.0.1", "compile-sass": "sass --update .:.", "compile-tsc": "tsc",