From d63a16ef8bde93b049146e97d6df6e60ff2e4fa0 Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 11 Nov 2020 16:38:48 +0300 Subject: [PATCH 01/12] Remove PHP ctype extension usage. --- build.html | 4 ++-- td/generate/TlDocumentationGenerator.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.html b/build.html index 2a2bab1c8..ae6629c72 100644 --- a/build.html +++ b/build.html @@ -604,7 +604,7 @@ function onOptionsChanged() { case 'Alpine': commands.push(sudo + 'apk update'); commands.push(sudo + 'apk upgrade'); - var packages = 'alpine-sdk linux-headers git zlib-dev openssl-dev gperf php php-ctype cmake'; + var packages = 'alpine-sdk linux-headers git zlib-dev openssl-dev gperf php cmake'; if (target === 'JNI') { packages += ' openjdk8'; } @@ -676,7 +676,7 @@ function onOptionsChanged() { } } else if (os_freebsd) { commands.push(sudo + 'pkg upgrade'); - var packages = 'git gperf php72 php72-ctype cmake'; + var packages = 'git gperf php72 cmake'; if (target === 'JNI') { packages += ' openjdk'; } diff --git a/td/generate/TlDocumentationGenerator.php b/td/generate/TlDocumentationGenerator.php index 9346fae14..0882b3326 100644 --- a/td/generate/TlDocumentationGenerator.php +++ b/td/generate/TlDocumentationGenerator.php @@ -53,7 +53,7 @@ abstract class TlDocumentationGenerator } } if ($bracket_count === 0) { - if (ctype_upper($str[$pos + 1])) { + if (ord('A') <= ord($str[$pos + 1]) && ord($str[$pos + 1]) <= ord('Z')) { return substr($str, 0, -1).'.)'; } } else { From 9725780fc6e4b8f7f47190eb150cd6f6b249074f Mon Sep 17 00:00:00 2001 From: levlam Date: Wed, 11 Nov 2020 16:39:45 +0300 Subject: [PATCH 02/12] Replace referenced text with anchor name in richTextReference to support nested references. --- td/generate/scheme/td_api.tl | 8 ++++---- td/generate/scheme/td_api.tlo | Bin 185260 -> 185260 bytes td/telegram/WebPageBlock.cpp | 7 ++----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 67d6b1576..e878e9026 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1053,14 +1053,14 @@ richTextPhoneNumber text:RichText phone_number:string = RichText; //@height Height of a bounding box in which the image should be shown; 0 if unknown richTextIcon document:document width:int32 height:int32 = RichText; -//@description A rich text reference of a text on the same web page @text The text @reference_text The text to show on click @url An HTTP URL, opening the reference -richTextReference text:RichText reference_text:RichText url:string = RichText; +//@description A reference to a richTexts object on the same web page @text The text @anchor_name The name of a richTextAnchor object, which is the first element of the target richTexts object @url An HTTP URL, opening the reference +richTextReference text:RichText anchor_name:string url:string = RichText; //@description An anchor @name Anchor name richTextAnchor name:string = RichText; -//@description A link to an anchor on the same web page @text The link text @name The anchor name. If the name is empty, the link should bring back to top @url An HTTP URL, opening the anchor -richTextAnchorLink text:RichText name:string url:string = RichText; +//@description A link to an anchor on the same web page @text The link text @anchor_name The anchor name. If the name is empty, the link should bring back to top @url An HTTP URL, opening the anchor +richTextAnchorLink text:RichText anchor_name:string url:string = RichText; //@description A concatenation of rich texts @texts Texts richTexts texts:vector = RichText; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index bd9fdf227bd47a3e5a75053f6f40e485c68661d0..648454218e5dadd27f79d9a49cfa5be3a894e08f 100644 GIT binary patch delta 971 zcmZ3poO{i3?hQF=EGs+bWj7b7Z7)z`+#m_&O;2!SRG9AKz-WWSUE;uK0pUJyV61^l z#6VaF92rC4VhYnOoM4KIwBZEV!vF%)_a0=_pI+d|C@@{Znb8ESZF_(-V+13_ zgf%XVGDv2jeUn6>?kA7c)>iQ8iW7;i9v<(FFo zL(QGm%P2GXK)VRUfP!vD1uzRFECF{k(A`DOY&smaZ3jVO(@zkmOreKSg$UDXdKfi` zPxIDx{XOla2b=@TX}LL(d$8e+(5 zq@Uf_&d8sh*Tg6{S;qyEAf_u!gt~S5flMX?9b`QqbFW>JUm^qxYe$g&BA?8> iYzC0J>BQS2FbS6Y4JI)f;0%)Xib;&yD<(0SI068#w@jV@ delta 969 zcmZ3poO{i3?hQF=EU890nau@i+Y8hfH%Nkc(-RyS6{fp5Fxnt-mpCw5K)4Sa7;E4X zF%Z@PN5&Ain8I`mCzxWeQB#~4Z8$;pFo3}Hy$2cfrx!Rf3QU)9W;6k7+aBP|7{LfJ zVT}u;43b%ITwrFQN^H+?W!%9IQK;g}_yWQb@MGKoW^F&?$C!g|;`W#T#v4pv`Q;YD zP;;mCGRjOo&@KWoprD&k0n7pkOTZlsba#<6n+}I<+d+`n^b^D>Q|Mt-A;Pqp9!3o! zl-=n;a+?J%w}As0NL-cUiV-=_z{*{enVb=lT2T^OlmpT;c}}nlD_Ha7!qe)L56otn zzMvQC%;_h3p)Q%^B7+oVg3*k|knjoUBg#i>h*QSVkK`lVp`FkVwG`+oh|{MB+B51; zK48QFan%!`Ibi4BJSODBJUMWm&g8uhttU5_bBG`Z6DUZs-pD=+D65pV}&_z}v z{p`LbUr}mWYEf!la%y}DFx0nQL(texts[0].get_rich_text_object(context), anchor.str(), content); } else { - context->is_first_pass_ = true; - auto reference_text = it->second->get_rich_text_object(context); - context->is_first_pass_ = false; - return make_tl_object(texts[0].get_rich_text_object(context), - std::move(reference_text), content); + return make_tl_object(texts[0].get_rich_text_object(context), anchor.str(), + content); } } } From 597c0d2983e39bb754553c254389a2bc2cd95384 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 12 Nov 2020 01:19:30 +0300 Subject: [PATCH 03/12] Add checks that client ID doesn't overflow. --- td/telegram/Client.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/td/telegram/Client.cpp b/td/telegram/Client.cpp index 1e7658dc1..9cc4cf9a9 100644 --- a/td/telegram/Client.cpp +++ b/td/telegram/Client.cpp @@ -86,6 +86,7 @@ class ClientManager::Impl final { concurrent_scheduler_->init(0); concurrent_scheduler_->start(); } + CHECK(client_id_ != std::numeric_limits::max()); auto client_id = ++client_id_; tds_[client_id] = concurrent_scheduler_->create_actor_unsafe(0, "Td", receiver_.create_callback(client_id), options_); @@ -362,7 +363,7 @@ class MultiImpl { } static bool is_valid_client_id(int32 client_id) { - return client_id > 0 && client_id < current_id_.load(); + return client_id > 0 && static_cast(client_id) < current_id_.load(); } void send(ClientManager::ClientId client_id, ClientManager::RequestId request_id, @@ -393,10 +394,12 @@ class MultiImpl { thread scheduler_thread_; ActorOwn multi_td_; - static std::atomic current_id_; + static std::atomic current_id_; static int32 create_id() { - return current_id_.fetch_add(1); + auto result = current_id_.fetch_add(1); + CHECK(result <= static_cast(std::numeric_limits::max())); + return static_cast(result); } void create(int32 td_id, unique_ptr callback) { @@ -405,7 +408,7 @@ class MultiImpl { } }; -std::atomic MultiImpl::current_id_{1}; +std::atomic MultiImpl::current_id_{1}; class MultiImplPool { public: From 6a9cd7263680b2f73424cdf4611f1082c1c78174 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 12 Nov 2020 14:45:18 +0300 Subject: [PATCH 04/12] Don't create client through ClientManager until first request is sent to it. --- td/telegram/Client.cpp | 77 +++++++++++++++++++++------------- td/telegram/Client.h | 1 + td/telegram/ClientJson.cpp | 8 ++-- td/telegram/ClientJson.h | 8 ++-- td/telegram/td_json_client.cpp | 8 ++-- td/telegram/td_json_client.h | 4 +- test/tdclient.cpp | 6 ++- 7 files changed, 66 insertions(+), 46 deletions(-) diff --git a/td/telegram/Client.cpp b/td/telegram/Client.cpp index 9cc4cf9a9..c56fdd82a 100644 --- a/td/telegram/Client.cpp +++ b/td/telegram/Client.cpp @@ -78,22 +78,25 @@ class TdReceiver { class ClientManager::Impl final { public: ClientId create_client() { - if (tds_.empty()) { - CHECK(concurrent_scheduler_ == nullptr); - CHECK(options_.net_query_stats == nullptr); - options_.net_query_stats = std::make_shared(); - concurrent_scheduler_ = make_unique(); - concurrent_scheduler_->init(0); - concurrent_scheduler_->start(); - } CHECK(client_id_ != std::numeric_limits::max()); auto client_id = ++client_id_; - tds_[client_id] = - concurrent_scheduler_->create_actor_unsafe(0, "Td", receiver_.create_callback(client_id), options_); + pending_clients_.insert(client_id); return client_id; } void send(ClientId client_id, RequestId request_id, td_api::object_ptr &&request) { + if (pending_clients_.erase(client_id) != 0) { + if (tds_.empty()) { + CHECK(concurrent_scheduler_ == nullptr); + CHECK(options_.net_query_stats == nullptr); + options_.net_query_stats = std::make_shared(); + concurrent_scheduler_ = make_unique(); + concurrent_scheduler_->init(0); + concurrent_scheduler_->start(); + } + tds_[client_id] = + concurrent_scheduler_->create_actor_unsafe(0, "Td", receiver_.create_callback(client_id), options_); + } requests_.push_back({client_id, request_id, std::move(request)}); } @@ -196,6 +199,7 @@ class ClientManager::Impl final { unique_ptr concurrent_scheduler_; ClientId client_id_{0}; Td::Options options_; + std::unordered_set pending_clients_; std::unordered_map> tds_; }; @@ -356,10 +360,15 @@ class MultiImpl { MultiImpl(MultiImpl &&) = delete; MultiImpl &operator=(MultiImpl &&) = delete; - int32 create(TdReceiver &receiver) { - auto id = create_id(); - create(id, receiver.create_callback(id)); - return id; + static int32 create_id() { + auto result = current_id_.fetch_add(1); + CHECK(result <= static_cast(std::numeric_limits::max())); + return static_cast(result); + } + + void create(int32 td_id, unique_ptr callback) { + auto guard = concurrent_scheduler_->get_send_guard(); + send_closure(multi_td_, &MultiTd::create, td_id, std::move(callback)); } static bool is_valid_client_id(int32 client_id) { @@ -395,17 +404,6 @@ class MultiImpl { ActorOwn multi_td_; static std::atomic current_id_; - - static int32 create_id() { - auto result = current_id_.fetch_add(1); - CHECK(result <= static_cast(std::numeric_limits::max())); - return static_cast(result); - } - - void create(int32 td_id, unique_ptr callback) { - auto guard = concurrent_scheduler_->get_send_guard(); - send_closure(multi_td_, &MultiTd::create, td_id, std::move(callback)); - } }; std::atomic MultiImpl::current_id_{1}; @@ -458,11 +456,10 @@ class MultiImplPool { class ClientManager::Impl final { public: ClientId create_client() { - auto impl = pool_.get(); - auto client_id = impl->create(receiver_); + auto client_id = MultiImpl::create_id(); { auto lock = impls_mutex_.lock_write().move_as_ok(); - impls_[client_id].impl = std::move(impl); + impls_[client_id]; // create empty MultiImplInfo } return client_id; } @@ -474,7 +471,22 @@ class ClientManager::Impl final { td_api::make_object(400, "Invalid TDLib instance specified")); return; } + auto it = impls_.find(client_id); + if (it != impls_.end() && it->second.impl == nullptr) { + lock.reset(); + + auto write_lock = impls_mutex_.lock_write().move_as_ok(); + it = impls_.find(client_id); + if (it != impls_.end() && it->second.impl == nullptr) { + it->second.impl = pool_.get(); + it->second.impl->create(client_id, receiver_.create_callback(client_id)); + } + write_lock.reset(); + + lock = impls_mutex_.lock_read().move_as_ok(); + it = impls_.find(client_id); + } if (it == impls_.end() || it->second.is_closed) { receiver_.add_response(client_id, request_id, td_api::make_object(500, "Request aborted")); return; @@ -517,7 +529,11 @@ class ClientManager::Impl final { CHECK(it != impls_.end()); if (!it->second.is_closed) { it->second.is_closed = true; - it->second.impl->close(client_id); + if (it->second.impl == nullptr) { + receiver_.add_response(client_id, 0, nullptr); + } else { + it->second.impl->close(client_id); + } } } @@ -554,7 +570,8 @@ class Client::Impl final { Impl() { static MultiImplPool pool; multi_impl_ = pool.get(); - td_id_ = multi_impl_->create(receiver_); + td_id_ = MultiImpl::create_id(); + multi_impl_->create(td_id_, receiver_.create_callback(td_id_)); } void send(Request request) { diff --git a/td/telegram/Client.h b/td/telegram/Client.h index 7cb386def..ee1e2d755 100644 --- a/td/telegram/Client.h +++ b/td/telegram/Client.h @@ -184,6 +184,7 @@ class ClientManager final { /** * Creates a new TDLib client and returns its opaque identifier. + * The client will not send updates until the first request is sent to it. */ ClientId create_client(); diff --git a/td/telegram/ClientJson.cpp b/td/telegram/ClientJson.cpp index 1e4f37c57..960b55207 100644 --- a/td/telegram/ClientJson.cpp +++ b/td/telegram/ClientJson.cpp @@ -125,11 +125,11 @@ static std::mutex extra_mutex; static std::unordered_map extra; static std::atomic extra_id{1}; -int td_json_create_client() { +int json_create_client() { return static_cast(get_manager()->create_client()); } -void td_json_send(int client_id, Slice request) { +void json_send(int client_id, Slice request) { auto parsed_request = to_request(request); auto request_id = extra_id.fetch_add(1, std::memory_order_relaxed); if (!parsed_request.second.empty()) { @@ -139,7 +139,7 @@ void td_json_send(int client_id, Slice request) { get_manager()->send(client_id, request_id, std::move(parsed_request.first)); } -const char *td_json_receive(double timeout) { +const char *json_receive(double timeout) { auto response = get_manager()->receive(timeout); if (!response.object) { return nullptr; @@ -157,7 +157,7 @@ const char *td_json_receive(double timeout) { return store_string(from_response(*response.object, extra_str, response.client_id)); } -const char *td_json_execute(Slice request) { +const char *json_execute(Slice request) { auto parsed_request = to_request(request); return store_string( from_response(*ClientManager::execute(std::move(parsed_request.first)), parsed_request.second, 0)); diff --git a/td/telegram/ClientJson.h b/td/telegram/ClientJson.h index 9421b1d33..d7bc85125 100644 --- a/td/telegram/ClientJson.h +++ b/td/telegram/ClientJson.h @@ -33,12 +33,12 @@ class ClientJson final { std::atomic extra_id_{1}; }; -int td_json_create_client(); +int json_create_client(); -void td_json_send(int client_id, Slice request); +void json_send(int client_id, Slice request); -const char *td_json_receive(double timeout); +const char *json_receive(double timeout); -const char *td_json_execute(Slice request); +const char *json_execute(Slice request); } // namespace td diff --git a/td/telegram/td_json_client.cpp b/td/telegram/td_json_client.cpp index 3ddb5945c..c346a9048 100644 --- a/td/telegram/td_json_client.cpp +++ b/td/telegram/td_json_client.cpp @@ -31,17 +31,17 @@ const char *td_json_client_execute(void *client, const char *request) { } int td_create_client() { - return td::td_json_create_client(); + return td::json_create_client(); } void td_send(int client_id, const char *request) { - td::td_json_send(client_id, td::Slice(request == nullptr ? "" : request)); + td::json_send(client_id, td::Slice(request == nullptr ? "" : request)); } const char *td_receive(double timeout) { - return td::td_json_receive(timeout); + return td::json_receive(timeout); } const char *td_execute(const char *request) { - return td::td_json_execute(td::Slice(request == nullptr ? "" : request)); + return td::json_execute(td::Slice(request == nullptr ? "" : request)); } diff --git a/td/telegram/td_json_client.h b/td/telegram/td_json_client.h index 918e40522..f98705210 100644 --- a/td/telegram/td_json_client.h +++ b/td/telegram/td_json_client.h @@ -126,8 +126,8 @@ TDJSON_EXPORT void td_json_client_destroy(void *client); */ /** - * Creates a new instance of TDLib. - * \return Opaque indentifier of the created TDLib client. + * Creates a new instance of TDLib. The TDLib instance will not send updates until the first request is sent to it. + * \return Opaque indentifier of the created TDLib instance. */ TDJSON_EXPORT int td_create_client(); diff --git a/test/tdclient.cpp b/test/tdclient.cpp index 5217b33d8..800108b82 100644 --- a/test/tdclient.cpp +++ b/test/tdclient.cpp @@ -941,9 +941,11 @@ TEST(Client, Manager) { client.send(-1, 3, td::make_tl_object(3)); for (int i = 0; i < threads_n; i++) { threads.emplace_back([&] { - for (int i = 0; i < clients_n; i++) { + for (int i = 0; i <= clients_n; i++) { auto id = client.create_client(); - client.send(id, 3, td::make_tl_object(3)); + if (i != 0) { + client.send(id, 3, td::make_tl_object(3)); + } } }); } From 5ce7448f7a8c614b67ebbbf6892ffc36e05f2526 Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 12 Nov 2020 16:53:51 +0300 Subject: [PATCH 05/12] Send a dummy request to initialize client. --- example/java/org/drinkless/tdlib/Client.java | 1 + 1 file changed, 1 insertion(+) diff --git a/example/java/org/drinkless/tdlib/Client.java b/example/java/org/drinkless/tdlib/Client.java index e8bed6787..b923df391 100644 --- a/example/java/org/drinkless/tdlib/Client.java +++ b/example/java/org/drinkless/tdlib/Client.java @@ -188,6 +188,7 @@ public final class Client { if (defaultExceptionHandler != null) { defaultExceptionHandlers.put(nativeClientId, defaultExceptionHandler); } + send(new TdApi.GetAuthorizationState(), null, null); } @Override From f5dadbb1e508833dc0723bf3cdfe3d27e767731e Mon Sep 17 00:00:00 2001 From: levlam Date: Thu, 12 Nov 2020 17:32:12 +0300 Subject: [PATCH 06/12] Automatically install dependent DLLs on Windows. --- CMakeLists.txt | 3 +++ example/java/CMakeLists.txt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index ed6e4d5fa..2f0e6de47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -882,6 +882,9 @@ install(FILES "${TL_TD_AUTO_INCLUDE_DIR}/td/telegram/td_api.h" "${TL_TD_AUTO_INC if (TD_ENABLE_JNI) install(FILES td/tl/tl_jni_object.h DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/td/tl") endif() +if (MSVC AND VCPKG_TOOLCHAIN) + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$/" DESTINATION "${CMAKE_INSTALL_BINDIR}" FILES_MATCHING PATTERN "*.dll") +endif() include(CMakePackageConfigHelpers) write_basic_package_version_file("TdConfigVersion.cmake" diff --git a/example/java/CMakeLists.txt b/example/java/CMakeLists.txt index 46373743f..057c8eca9 100644 --- a/example/java/CMakeLists.txt +++ b/example/java/CMakeLists.txt @@ -105,3 +105,6 @@ install(TARGETS tdjni LIBRARY DESTINATION bin RUNTIME DESTINATION bin ) +if (MSVC AND VCPKG_TOOLCHAIN) + install(DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/$/" DESTINATION bin FILES_MATCHING PATTERN "*.dll" PATTERN "*.pdb") +endif() From 15b1543e20271cbf24c6e2870f24d581510393d8 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 13 Nov 2020 15:54:38 +0300 Subject: [PATCH 07/12] Implement OS detection in Emscripten. --- tdutils/td/utils/port/uname.cpp | 98 ++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) diff --git a/tdutils/td/utils/port/uname.cpp b/tdutils/td/utils/port/uname.cpp index ee0fde119..c3694e74d 100644 --- a/tdutils/td/utils/port/uname.cpp +++ b/tdutils/td/utils/port/uname.cpp @@ -20,6 +20,10 @@ #if TD_ANDROID #include +#elif TD_EMSCRIPTEN +#include + +#include #else #if TD_DARWIN #include @@ -90,6 +94,98 @@ Slice get_operating_system_version() { if (length > 0) { return "Android " + string(version, length); } +#elif TD_EMSCRIPTEN + // clang-format off + char *os_name_js = (char*)EM_ASM_INT(({ + function detectOsName() { + if (typeof process === 'object' && typeof process.platform === 'string') { // Node.js + switch (process.platform) { + case 'aix': + return 'IBM AIX'; + case 'android': + return 'Android'; + case 'darwin': + return 'macOS'; + case 'freebsd': + return 'FreeBSD'; + case 'linux': + return 'Linux'; + case 'openbsd': + return 'OpenBSD'; + case 'sunos': + return 'SunOS'; + case 'win32': + return 'Windows'; + case 'darwin': + return 'macOS'; + default: + return 'Node.js'; + } + } + + var userAgent = 'Unknown'; + if (typeof window === 'object') { // Web + userAgent = window.navigator.userAgent; + } else if (typeof importScripts === 'function') { // Web Worker + userAgent = navigator.userAgent; + } + + var match = /(Mac OS|Mac OS X|MacPPC|MacIntel|Mac_PowerPC|Macintosh) ([._0-9]+)/.exec(userAgent); + if (match !== null) { + return 'macOS ' + match[2].replace('_', '.'); + } + + match = /Android [._0-9]+/.exec(userAgent); + if (match !== null) { + return match[0].replace('_', '.'); + } + + if (/(iPhone|iPad|iPod)/.test(userAgent)) { + match = /OS ([._0-9]+)/.exec(userAgent); + if (match !== null) { + return 'iOS ' + match[1].replace('_', '.'); + } + return 'iOS'; + } + + var clientStrings = [ + {s:'Windows 10', r:/(Windows 10.0|Windows NT 10.0)/}, + {s:'Windows 8.1', r:/(Windows 8.1|Windows NT 6.3)/}, + {s:'Windows 8', r:/(Windows 8|Windows NT 6.2)/}, + {s:'Windows 7', r:/(Windows 7|Windows NT 6.1)/}, + {s:'Windows Vista', r:/Windows NT 6.0/}, + {s:'Windows Server 2003', r:/Windows NT 5.2/}, + {s:'Windows XP', r:/(Windows XP|Windows NT 5.1)/}, + {s:'Windows', r:/Windows/}, + {s:'Android', r:/Android/}, + {s:'FreeBSD', r:/FreeBSD/}, + {s:'OpenBSD', r:/OpenBSD/}, + {s:'Chrome OS', r:/CrOS/}, + {s:'Linux', r:/(Linux|X11)/}, + {s:'macOS', r:/(Mac OS|MacPPC|MacIntel|Mac_PowerPC|Macintosh)/}, + {s:'QNX', r:/QNX/}, + {s:'BeOS', r:/BeOS/} + ]; + for (var id in clientStrings) { + var cs = clientStrings[id]; + if (cs.r.test(userAgent)) { + return cs.s; + } + } + return 'Emscripten'; + } + + var os_name = detectOsName(); + var length = lengthBytesUTF8(os_name) + 1; + var result = _malloc(length); + stringToUTF8(os_name, result, length); + return result; + })); + // clang-format on + string os_name(os_name_js); + std::free(os_name_js); + + return os_name; #else #if TD_LINUX auto os_name = read_os_name("/etc/os-release", "PRETTY_NAME=\"", "\"\n"); @@ -124,8 +220,6 @@ Slice get_operating_system_version() { return "NetBSD"; #elif TD_CYGWIN return "Cygwin"; -#elif TD_EMSCRIPTEN - return "Emscripten"; #else return "Unix"; #endif From 1d9f2835d242626689a4d2a70608952dc99085ce Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 13 Nov 2020 18:17:23 +0300 Subject: [PATCH 08/12] Silence SQLite build warnings. --- sqlite/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlite/CMakeLists.txt b/sqlite/CMakeLists.txt index a11f5c75f..b439b0cd6 100644 --- a/sqlite/CMakeLists.txt +++ b/sqlite/CMakeLists.txt @@ -50,7 +50,7 @@ endif() if (GCC OR CLANG) target_compile_options(tdsqlite PRIVATE -Wno-deprecated-declarations -Wno-unused-variable -Wno-unused-const-variable -Wno-unused-function) if (CLANG) - target_compile_options(tdsqlite PRIVATE -Wno-parentheses-equality -Wno-unused-value) + target_compile_options(tdsqlite PRIVATE -Wno-parentheses-equality -Wno-unused-value -Wno-unused-command-line-argument -Qunused-arguments) endif() if (GCC AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 10.0)) target_compile_options(tdsqlite PRIVATE -Wno-return-local-addr -Wno-stringop-overflow) From 326fd203e9838e3b9a0f865eb2c3f6f4449b9fc3 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 13 Nov 2020 12:55:24 +0300 Subject: [PATCH 09/12] Fix documentation misprint. --- td/generate/scheme/td_api.tl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index e878e9026..183bad19f 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -3790,7 +3790,7 @@ getMessageLinkInfo url:string = MessageLinkInfo; //@reply_markup Markup for replying to the message; for bots only @input_message_content The content of the message to be sent sendMessage chat_id:int53 message_thread_id:int53 reply_to_message_id:int53 options:messageSendOptions reply_markup:ReplyMarkup input_message_content:InputMessageContent = Message; -//@description Sends messages grouped together into an album. Currently only audio, document, photo and video messages can be grouped into an album. Documents and audio files can be only groupув in an album with messages of the same type. Returns sent messages +//@description Sends messages grouped together into an album. Currently only audio, document, photo and video messages can be grouped into an album. Documents and audio files can be only grouped in an album with messages of the same type. Returns sent messages //@chat_id Target chat //@message_thread_id If not 0, a message thread identifier in which the messages will be sent //@reply_to_message_id Identifier of a message to reply to or 0 From 3efc530fc4234da6bf535a7f1ed8ceed468fbb06 Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 13 Nov 2020 18:42:47 +0300 Subject: [PATCH 10/12] Use ClientManager in check_proxy. --- benchmark/check_proxy.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/benchmark/check_proxy.cpp b/benchmark/check_proxy.cpp index a493b1c46..e1ff5523e 100644 --- a/benchmark/check_proxy.cpp +++ b/benchmark/check_proxy.cpp @@ -160,20 +160,22 @@ int main(int argc, char **argv) { SET_VERBOSITY_LEVEL(new_verbosity_level); - td::Client client; + td::ClientManager client_manager; + auto client_id = client_manager.create_client(); for (size_t i = 0; i < requests.size(); i++) { auto &request = requests[i].second; request->dc_id_ = dc_id; request->timeout_ = timeout; - client.send({i + 1, std::move(request)}); + client_manager.send(client_id, i + 1, std::move(request)); } size_t successful_requests = 0; size_t failed_requests = 0; while (successful_requests + failed_requests != requests.size()) { - auto response = client.receive(100.0); - if (1 <= response.id && response.id <= requests.size()) { - auto &proxy = requests[static_cast(response.id - 1)].first; + auto response = client_manager.receive(100.0); + CHECK(client_id == response.client_id); + if (1 <= response.request_id && response.request_id <= requests.size()) { + auto &proxy = requests[static_cast(response.request_id - 1)].first; if (response.object->get_id() == td::td_api::error::ID) { LOG(ERROR) << proxy << ": " << to_string(response.object); failed_requests++; From 012353aef5900fc4eaf284d0723bf013f73a622d Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 13 Nov 2020 19:16:11 +0300 Subject: [PATCH 11/12] Update JSON C++ example. --- example/cpp/README.md | 2 +- example/cpp/tdjson_example.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/example/cpp/README.md b/example/cpp/README.md index addc1d4f7..1658ade6f 100644 --- a/example/cpp/README.md +++ b/example/cpp/README.md @@ -21,4 +21,4 @@ cmake --build . Documentation for all available classes and methods can be found at https://core.telegram.org/tdlib/docs. -To run `tdjson_example` you may need to manually copy a `tdjson` shared library from `td/bin` to a directory containing built binaries. +To run the examples you may need to manually copy needed shared libraries from `td/bin` to a directory containing built binaries. diff --git a/example/cpp/tdjson_example.cpp b/example/cpp/tdjson_example.cpp index 5d69c4e21..62978f178 100644 --- a/example/cpp/tdjson_example.cpp +++ b/example/cpp/tdjson_example.cpp @@ -18,6 +18,9 @@ int main() { int client_id = td_create_client(); // somehow share the client_id with other threads, which will be able to send requests via td_send + // start the client by sending request to it + td_send(client_id, "{\"@type\":\"getOption\", \"name\":\"version\"}"); + const bool test_incorrect_queries = false; if (test_incorrect_queries) { td_execute("{\"@type\":\"setLogVerbosityLevel\", \"new_verbosity_level\":1}"); From 00abe2f4019717c6479e30c588059a3cfd3be58e Mon Sep 17 00:00:00 2001 From: levlam Date: Fri, 13 Nov 2020 19:22:57 +0300 Subject: [PATCH 12/12] Use ClientManager in C++ example. --- example/cpp/td_example.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/example/cpp/td_example.cpp b/example/cpp/td_example.cpp index 4771e5417..4bb493857 100644 --- a/example/cpp/td_example.cpp +++ b/example/cpp/td_example.cpp @@ -53,8 +53,10 @@ namespace td_api = td::td_api; class TdExample { public: TdExample() { - td::Client::execute({0, td_api::make_object(1)}); - client_ = std::make_unique(); + td::ClientManager::execute(td_api::make_object(1)); + client_manager_ = std::make_unique(); + client_id_ = client_manager_->create_client(); + send_query(td_api::make_object("version"), {}); } void loop() { @@ -62,7 +64,7 @@ class TdExample { if (need_restart_) { restart(); } else if (!are_authorized_) { - process_response(client_->receive(10)); + process_response(client_manager_->receive(10)); } else { std::cout << "Enter action [q] quit [u] check for updates and request results [c] show chats [m ] " "send message [me] show self [l] logout: " @@ -80,7 +82,7 @@ class TdExample { if (action == "u") { std::cout << "Checking for updates..." << std::endl; while (true) { - auto response = client_->receive(0); + auto response = client_manager_->receive(0); if (response.object) { process_response(std::move(response)); } else { @@ -131,7 +133,8 @@ class TdExample { private: using Object = td_api::object_ptr; - std::unique_ptr client_; + std::unique_ptr client_manager_; + std::int32_t client_id_{0}; td_api::object_ptr authorization_state_; bool are_authorized_{false}; @@ -146,7 +149,7 @@ class TdExample { std::map chat_title_; void restart() { - client_.reset(); + client_manager_.reset(); *this = TdExample(); } @@ -155,18 +158,18 @@ class TdExample { if (handler) { handlers_.emplace(query_id, std::move(handler)); } - client_->send({query_id, std::move(f)}); + client_manager_->send(client_id_, query_id, std::move(f)); } - void process_response(td::Client::Response response) { + void process_response(td::ClientManager::Response response) { if (!response.object) { return; } - //std::cout << response.id << " " << to_string(response.object) << std::endl; - if (response.id == 0) { + //std::cout << response.request_id << " " << to_string(response.object) << std::endl; + if (response.request_id == 0) { return process_update(std::move(response.object)); } - auto it = handlers_.find(response.id); + auto it = handlers_.find(response.request_id); if (it != handlers_.end()) { it->second(std::move(response.object)); }