Merge commit 'cecdae448e88603c98d7d079855c992be6df739f'

This commit is contained in:
Andrea Cavalli 2020-10-20 23:20:56 +02:00
commit 17230da76a
15 changed files with 183 additions and 50 deletions

View File

@ -0,0 +1,80 @@
function(get_relative_link OUTPUT PATH)
if (PATH MATCHES "^[$]<[$]<CONFIG:DEBUG>:")
set(${OUTPUT} "" PARENT_SCOPE)
return()
endif()
string(REGEX REPLACE "^[$]<[$]<NOT:[$]<CONFIG:DEBUG>>:(.*)>$" "\\1" PATH "${PATH}")
get_filename_component(NAME "${PATH}" NAME_WE)
if (IS_ABSOLUTE ${PATH})
get_filename_component(DIRECTORY_NAME "${PATH}" DIRECTORY)
if (WIN32)
set(${OUTPUT} "-l\"${DIRECTORY_NAME}/${NAME}\"" PARENT_SCOPE)
else()
get_filename_component(FULL_NAME "${PATH}" NAME)
set(${OUTPUT} "-L\"${DIRECTORY_NAME}\" -l:${FULL_NAME}" PARENT_SCOPE)
endif()
return()
endif()
if (NOT WIN32 AND NAME MATCHES "^lib")
string(REGEX REPLACE "^lib" "-l" LINK "${NAME}")
elseif (NAME MATCHES "^-")
set(LINK "${NAME}")
else()
string(CONCAT LINK "-l" "${NAME}")
endif()
set(${OUTPUT} "${LINK}" PARENT_SCOPE)
endfunction()
function(generate_pkgconfig TARGET DESCRIPTION)
# message("Generating pkg-config for ${TARGET}")
get_filename_component(PREFIX "${CMAKE_INSTALL_PREFIX}" REALPATH)
get_target_property(LIST "${TARGET}" LINK_LIBRARIES)
set(REQS "")
set(LIBS "")
foreach (LIB ${LIST})
if (TARGET "${LIB}")
set(HAS_REQS 1)
list(APPEND REQS "${LIB}")
else()
set(HAS_LIBS 1)
get_relative_link(LINK "${LIB}")
if (NOT LINK EQUAL "")
list(APPEND LIBS "${LINK}")
endif()
endif()
endforeach()
if (HAS_REQS)
set(REQUIRES "")
foreach (REQ ${REQS})
set(REQUIRES "${REQUIRES} ${REQ}")
endforeach()
set(REQUIRES "Requires.private:${REQUIRES}\n")
endif()
if (HAS_LIBS)
set(LIBRARIES "")
list(REVERSE LIBS)
list(REMOVE_DUPLICATES LIBS)
foreach (LIB ${LIBS})
set(LIBRARIES " ${LIB}${LIBRARIES}")
endforeach()
set(LIBRARIES "Libs.private:${LIBRARIES}\n")
endif()
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig")
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/${TARGET}.pc" CONTENT
"prefix=${PREFIX}
Name: ${TARGET}
Description: ${DESCRIPTION}
Version: ${PROJECT_VERSION}
CFlags: -I\"\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}\"
Libs: -L\"\${prefix}/${CMAKE_INSTALL_LIBDIR}\" -l${TARGET}
${REQUIRES}${LIBRARIES}")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/${TARGET}.pc" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig")
endfunction()

View File

@ -988,6 +988,28 @@ install(TARGETS tdjson TdJson tdjson_static TdJsonStatic tdjson_private tdclient
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
)
# generate pkg-config files
include(GeneratePkgConfig)
generate_pkgconfig(tdutils "Telegram Library - Utils")
generate_pkgconfig(tdactor "Telegram Library - Actor")
generate_pkgconfig(tdnet "Telegram Library - Net")
generate_pkgconfig(tdsqlite "Telegram Library - SQLite")
generate_pkgconfig(tddb "Telegram Library - Database")
if (MEMPROF)
# generate_pkgconfig(memprof "memprof - simple library for memory usage profiling")
endif()
generate_pkgconfig(tdcore "Telegram Library - Core")
generate_pkgconfig(tdclient "Telegram Library - C++ Interface")
if (TD_ENABLE_DOTNET)
# generate_pkgconfig(tddotnet "Telegram Library - C# Interface")
endif()
# generate_pkgconfig(tdc "Telegram Library - C interface")
generate_pkgconfig(tdapi "Telegram Library - API")
generate_pkgconfig(tdjson_private "Telegram Library - JSON interface (private)")
generate_pkgconfig(tdjson "Telegram Library - JSON interface (shared)")
generate_pkgconfig(tdjson_static "Telegram Library - JSON interface (static)")
install(EXPORT TdTargets
FILE TdTargets.cmake
NAMESPACE Td::

View File

@ -257,7 +257,7 @@ class TdExample {
[this](td_api::authorizationStateWaitPassword &) {
std::cout << "Enter authentication password: " << std::flush;
std::string password;
std::cin >> password;
std::getline(std::cin, line);
send_query(td_api::make_object<td_api::checkAuthenticationPassword>(password),
create_authentication_query_handler());
},

View File

@ -149,6 +149,7 @@ public final class Client {
if (isClosed) {
updateHandlers.remove(clientId); // there will be no more updates
defaultExceptionHandlers.remove(clientId); // ignore further exceptions
clientCount.decrementAndGet();
}
}
@ -164,6 +165,7 @@ public final class Client {
private static final ConcurrentHashMap<Integer, Handler> updateHandlers = new ConcurrentHashMap<Integer, Handler>();
private static final ConcurrentHashMap<Long, Handler> handlers = new ConcurrentHashMap<Long, Handler>();
private static final AtomicLong currentQueryId = new AtomicLong();
private static final AtomicLong clientCount = new AtomicLong();
private static final ResponseReceiver responseReceiver = new ResponseReceiver();
@ -178,6 +180,7 @@ public final class Client {
}
private Client(ResultHandler updateHandler, ExceptionHandler updateExceptionHandler, ExceptionHandler defaultExceptionHandler) {
clientCount.incrementAndGet();
nativeClientId = createNativeClient();
if (updateHandler != null) {
updateHandlers.put(nativeClientId, new Handler(updateHandler, updateExceptionHandler));

View File

@ -2905,6 +2905,7 @@ ContactsManager::ContactsManager(Td *td, ActorShared<> parent) : td_(td), parent
G()->shared_config().set_option_integer("telegram_service_notifications_chat_id",
DialogId(get_service_notifications_user_id()).get());
G()->shared_config().set_option_integer("replies_bot_chat_id", DialogId(get_replies_bot_user_id()).get());
G()->shared_config().set_option_integer("group_anonymous_bot_user_id", get_anonymous_bot_user_id().get());
if (G()->parameters().use_chat_info_db) {
auto next_contacts_sync_date_string = G()->td_db()->get_binlog_pmc()->get("next_contacts_sync_date");

View File

@ -12521,8 +12521,8 @@ MessagesManager::MessageInfo MessagesManager::parse_telegram_api_message(
}
message_info.date = message->date_;
message_info.flags = message->flags_;
auto reply_to_message_id = MessageId(
ServerMessageId(message_info.reply_header == nullptr ? 0 : message_info.reply_header->reply_to_msg_id_));
auto reply_to_message_id =
MessageId(ServerMessageId(message->reply_to_ == nullptr ? 0 : message->reply_to_->reply_to_msg_id_));
message_info.content =
get_action_message_content(td_, std::move(message->action_), message_info.dialog_id, reply_to_message_id);
break;
@ -12565,9 +12565,9 @@ std::pair<DialogId, unique_ptr<MessagesManager::Message>> MessagesManager::creat
}
if (!is_broadcast_channel(dialog_id) && td_->auth_manager_->is_bot()) {
if (dialog_id == sender_dialog_id) {
sender_user_id = td_->contacts_manager_->add_anonymous_bot_user();
td_->contacts_manager_->add_anonymous_bot_user();
} else {
sender_user_id = td_->contacts_manager_->add_service_notifications_user();
td_->contacts_manager_->add_service_notifications_user();
}
}
}
@ -19590,7 +19590,6 @@ void MessagesManager::do_read_history_on_server(DialogId dialog_id) {
Dialog *d = get_dialog(dialog_id);
CHECK(d != nullptr);
CHECK(!d->updated_read_history_message_ids.empty());
for (auto top_thread_message_id : d->updated_read_history_message_ids) {
if (!top_thread_message_id.is_valid()) {

View File

@ -51,7 +51,7 @@ class RequestActor : public Actor {
CHECK(future.get_state() == FutureActor<T>::State::Waiting);
if (--tries_left_ == 0) {
future.close();
do_send_error(Status::Error(400, "Requested data is inaccessible"));
do_send_error(Status::Error(500, "Requested data is inaccessible"));
return stop();
}

View File

@ -41,7 +41,7 @@ class NetQueryStats {
void dump_pending_network_queries();
private:
NetQueryCounter::Counter count_;
NetQueryCounter::Counter count_{0};
std::atomic<bool> use_list_{true};
TsList<NetQueryDebug> list_;
};

View File

@ -115,10 +115,10 @@ class unique_ptr {
}
explicit unique_ptr(T *ptr) noexcept : ptr_(ptr) {
}
template <class S, class = std::enable_if_t<std::is_base_of<T, S>::value>>
template <class S, class = typename std::enable_if<std::is_base_of<T, S>::value>::type>
unique_ptr(unique_ptr<S> &&other) noexcept : ptr_(static_cast<S *>(other.release())) {
}
template <class S, class = std::enable_if_t<std::is_base_of<T, S>::value>>
template <class S, class = typename std::enable_if<std::is_base_of<T, S>::value>::type>
unique_ptr &operator=(unique_ptr<S> &&other) noexcept {
reset(static_cast<T *>(other.release()));
return *this;

View File

@ -52,11 +52,11 @@ set(TDNET_SOURCE
add_library(tdnet STATIC ${TDNET_SOURCE})
target_include_directories(tdnet PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)
target_include_directories(tdnet SYSTEM PRIVATE $<BUILD_INTERFACE:${OPENSSL_INCLUDE_DIR}>)
target_link_libraries(tdnet PUBLIC tdutils tdactor PRIVATE ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES})
target_link_libraries(tdnet PUBLIC tdutils tdactor)
if (NOT EMSCRIPTEN)
target_link_libraries(tdnet PRIVATE ${OPENSSL_SSL_LIBRARY})
endif()
target_link_libraries(tdnet PRIVATE ${OPENSSL_CRYPTO_LIBRARY})
target_link_libraries(tdnet PRIVATE ${OPENSSL_CRYPTO_LIBRARY} ${CMAKE_DL_LIBS} ${ZLIB_LIBRARIES})
if (WIN32)
if (MINGW)

View File

@ -483,7 +483,6 @@ void write_tl(const tl_config &config, tl_outputer &out, const TL_writer &w) {
std::size_t types_n = config.get_type_count();
std::size_t functions_n = config.get_function_count();
bool found_complex = false;
for (std::size_t type = 0; type < types_n; type++) {
tl_type *t = config.get_type_by_num(type);
assert(t->constructors_num == t->constructors.size());
@ -491,7 +490,6 @@ void write_tl(const tl_config &config, tl_outputer &out, const TL_writer &w) {
if (t->name == "Type") {
assert(t->id == ID_VAR_TYPE);
t->flags |= FLAG_COMPLEX;
found_complex = true;
}
continue;
}
@ -529,7 +527,6 @@ void write_tl(const tl_config &config, tl_outputer &out, const TL_writer &w) {
b.exist_var_num != -1) {
if (!w.is_built_in_complex_type(t->name)) {
t->flags |= FLAG_COMPLEX;
found_complex = true;
}
} else {
assert(b_arg_type == NODE_TYPE_TYPE);
@ -549,14 +546,13 @@ void write_tl(const tl_config &config, tl_outputer &out, const TL_writer &w) {
if (main_type == NODE_TYPE_VAR_TYPE) {
if (!w.is_built_in_complex_type(t->name)) {
t->flags |= FLAG_COMPLEX;
found_complex = true;
}
}
}
}
while (found_complex) {
found_complex = false;
while (true) {
bool found_complex = false;
for (std::size_t type = 0; type < types_n; type++) {
tl_type *t = config.get_type_by_num(type);
if (t->constructors_num == 0 || w.is_built_in_complex_type(t->name)) { // built-in dummy or complex types
@ -576,6 +572,9 @@ void write_tl(const tl_config &config, tl_outputer &out, const TL_writer &w) {
// std::fprintf(stderr, "Found complex %s\n", t->name.c_str());
}
}
if (!found_complex) {
break;
}
}
std::set<std::string> request_types;

View File

@ -384,17 +384,37 @@ class SocketFdImpl {
const NativeFd &get_native_fd() const {
return info.native_fd();
}
Result<size_t> writev(Span<IoSlice> slices) {
int native_fd = get_native_fd().socket();
auto write_res =
detail::skip_eintr([&] { return ::writev(native_fd, slices.begin(), narrow_cast<int>(slices.size())); });
TRY_RESULT(slices_size, narrow_cast_safe<int>(slices.size()));
auto write_res = detail::skip_eintr([&] {
#ifdef MSG_NOSIGNAL
msghdr msg;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = const_cast<iovec *>(slices.begin());
msg.msg_iovlen = slices_size;
return sendmsg(native_fd, &msg, MSG_NOSIGNAL);
#else
return ::writev(native_fd, slices.begin(), slices_size);
#endif
});
return write_finish(write_res);
}
Result<size_t> write(Slice slice) {
int native_fd = get_native_fd().socket();
auto write_res = detail::skip_eintr([&] { return ::write(native_fd, slice.begin(), slice.size()); });
auto write_res = detail::skip_eintr([&] {
return
#ifdef MSG_NOSIGNAL
send(native_fd, slice.begin(), slice.size(), MSG_NOSIGNAL);
#else
::write(native_fd, slice.begin(), slice.size());
#endif
});
return write_finish(write_res);
}
Result<size_t> write_finish(ssize_t write_res) {
auto write_errno = errno;
if (write_res >= 0) {
@ -538,6 +558,17 @@ Status init_socket_options(NativeFd &native_fd) {
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char *>(&flags), sizeof(flags));
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, reinterpret_cast<const char *>(&flags), sizeof(flags));
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<const char *>(&flags), sizeof(flags));
#if TD_PORT_POSIX
#ifndef MSG_NOSIGNAL // Darwin
#ifdef SO_NOSIGPIPE
setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<const char *>(&flags), sizeof(flags));
#else
#warning "Failed to suppress SIGPIPE signals. Use signal(SIGPIPE, SIG_IGN) to suppress them."
#endif
#endif
#endif
// TODO: SO_REUSEADDR, SO_KEEPALIVE, TCP_NODELAY, SO_SNDBUF, SO_RCVBUF, TCP_QUICKACK, SO_LINGER
return Status::OK();

View File

@ -47,7 +47,7 @@ class UdpSocketReceiveHelper {
public:
void to_native(const UdpMessage &message, WSAMSG &message_header) {
socklen_t addr_len{narrow_cast<socklen_t>(sizeof(addr_))};
message_header.name = reinterpret_cast<struct sockaddr *>(&addr_);
message_header.name = reinterpret_cast<sockaddr *>(&addr_);
message_header.namelen = addr_len;
buf_.buf = const_cast<char *>(message.data.as_slice().begin());
buf_.len = narrow_cast<DWORD>(message.data.size());
@ -59,8 +59,7 @@ class UdpSocketReceiveHelper {
}
void from_native(WSAMSG &message_header, size_t message_size, UdpMessage &message) {
message.address.init_sockaddr(reinterpret_cast<struct sockaddr *>(message_header.name), message_header.namelen)
.ignore();
message.address.init_sockaddr(reinterpret_cast<sockaddr *>(message_header.name), message_header.namelen).ignore();
message.error = Status::OK();
if ((message_header.dwFlags & (MSG_TRUNC | MSG_CTRUNC)) != 0) {
@ -82,7 +81,7 @@ class UdpSocketReceiveHelper {
class UdpSocketSendHelper {
public:
void to_native(const UdpMessage &message, WSAMSG &message_header) {
message_header.name = const_cast<struct sockaddr *>(message.address.get_sockaddr());
message_header.name = const_cast<sockaddr *>(message.address.get_sockaddr());
message_header.namelen = narrow_cast<socklen_t>(message.address.get_sockaddr_len());
buf_.buf = const_cast<char *>(message.data.as_slice().begin());
buf_.len = narrow_cast<DWORD>(message.data.size());
@ -373,7 +372,7 @@ void UdpSocketFdImplDeleter::operator()(UdpSocketFdImpl *impl) {
class UdpSocketReceiveHelper {
public:
void to_native(const UdpSocketFd::InboundMessage &message, struct msghdr &message_header) {
void to_native(const UdpSocketFd::InboundMessage &message, msghdr &message_header) {
socklen_t addr_len{narrow_cast<socklen_t>(sizeof(addr_))};
message_header.msg_name = &addr_;
@ -387,22 +386,22 @@ class UdpSocketReceiveHelper {
message_header.msg_flags = 0;
}
void from_native(struct msghdr &message_header, size_t message_size, UdpSocketFd::InboundMessage &message) {
void from_native(msghdr &message_header, size_t message_size, UdpSocketFd::InboundMessage &message) {
#if TD_LINUX
struct cmsghdr *cmsg;
struct sock_extended_err *ee = nullptr;
cmsghdr *cmsg;
sock_extended_err *ee = nullptr;
for (cmsg = CMSG_FIRSTHDR(&message_header); cmsg != nullptr; cmsg = CMSG_NXTHDR(&message_header, cmsg)) {
if (cmsg->cmsg_type == IP_PKTINFO && cmsg->cmsg_level == IPPROTO_IP) {
//auto *pi = reinterpret_cast<struct in_pktinfo *>(CMSG_DATA(cmsg));
//auto *pi = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsg));
} else if (cmsg->cmsg_type == IPV6_PKTINFO && cmsg->cmsg_level == IPPROTO_IPV6) {
//auto *pi = reinterpret_cast<struct in6_pktinfo *>(CMSG_DATA(cmsg));
//auto *pi = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsg));
} else if ((cmsg->cmsg_type == IP_RECVERR && cmsg->cmsg_level == IPPROTO_IP) ||
(cmsg->cmsg_type == IPV6_RECVERR && cmsg->cmsg_level == IPPROTO_IPV6)) {
ee = reinterpret_cast<struct sock_extended_err *>(CMSG_DATA(cmsg));
ee = reinterpret_cast<sock_extended_err *>(CMSG_DATA(cmsg));
}
}
if (ee != nullptr) {
auto *addr = reinterpret_cast<struct sockaddr *>(SO_EE_OFFENDER(ee));
auto *addr = reinterpret_cast<sockaddr *>(SO_EE_OFFENDER(ee));
IPAddress address;
address.init_sockaddr(addr).ignore();
if (message.from != nullptr) {
@ -417,8 +416,7 @@ class UdpSocketReceiveHelper {
}
#endif
if (message.from != nullptr) {
message.from
->init_sockaddr(reinterpret_cast<struct sockaddr *>(message_header.msg_name), message_header.msg_namelen)
message.from->init_sockaddr(reinterpret_cast<sockaddr *>(message_header.msg_name), message_header.msg_namelen)
.ignore();
}
if (message.error) {
@ -439,14 +437,14 @@ class UdpSocketReceiveHelper {
private:
std::array<char, 1024> control_buf_;
sockaddr_storage addr_;
struct iovec io_vec_;
iovec io_vec_;
};
class UdpSocketSendHelper {
public:
void to_native(const UdpSocketFd::OutboundMessage &message, struct msghdr &message_header) {
void to_native(const UdpSocketFd::OutboundMessage &message, msghdr &message_header) {
CHECK(message.to != nullptr && message.to->is_valid());
message_header.msg_name = const_cast<struct sockaddr *>(message.to->get_sockaddr());
message_header.msg_name = const_cast<sockaddr *>(message.to->get_sockaddr());
message_header.msg_namelen = narrow_cast<socklen_t>(message.to->get_sockaddr_len());
io_vec_.iov_base = const_cast<char *>(message.data.begin());
io_vec_.iov_len = message.data.size();
@ -459,7 +457,7 @@ class UdpSocketSendHelper {
}
private:
struct iovec io_vec_;
iovec io_vec_;
};
class UdpSocketFdImpl {
@ -495,7 +493,7 @@ class UdpSocketFdImpl {
#endif
}
struct msghdr message_header;
msghdr message_header;
detail::UdpSocketReceiveHelper helper;
helper.to_native(message, message_header);
@ -549,7 +547,7 @@ class UdpSocketFdImpl {
Status send_message(const UdpSocketFd::OutboundMessage &message, bool &is_sent) {
is_sent = false;
struct msghdr message_header;
msghdr message_header;
detail::UdpSocketSendHelper helper;
helper.to_native(message, message_header);
@ -651,11 +649,11 @@ class UdpSocketFdImpl {
#if TD_HAS_MMSG
Status send_messages_fast(Span<UdpSocketFd::OutboundMessage> messages, size_t &cnt) {
//struct mmsghdr {
// struct msghdr msg_hdr; [> Message header <]
// msghdr msg_hdr; [> Message header <]
// unsigned int msg_len; [> Number of bytes transmitted <]
//};
struct std::array<detail::UdpSocketSendHelper, 16> helpers;
struct std::array<struct mmsghdr, 16> headers;
std::array<detail::UdpSocketSendHelper, 16> helpers;
std::array<mmsghdr, 16> headers;
size_t to_send = min(messages.size(), headers.size());
for (size_t i = 0; i < to_send; i++) {
helpers[i].to_native(messages[i], headers[i].msg_hdr);
@ -702,11 +700,11 @@ class UdpSocketFdImpl {
#endif
}
//struct mmsghdr {
// struct msghdr msg_hdr; [> Message header <]
// msghdr msg_hdr; [> Message header <]
// unsigned int msg_len; [> Number of bytes transmitted <]
//};
struct std::array<detail::UdpSocketReceiveHelper, 16> helpers;
struct std::array<struct mmsghdr, 16> headers;
std::array<detail::UdpSocketReceiveHelper, 16> helpers;
std::array<mmsghdr, 16> headers;
size_t to_receive = min(messages.size(), headers.size());
for (size_t i = 0; i < to_receive; i++) {
helpers[i].to_native(messages[i], headers[i].msg_hdr);

View File

@ -67,7 +67,7 @@ void EventFdLinux::release() {
auto native_fd = impl_->info.native_fd().fd();
auto result = [&]() -> Result<size_t> {
auto write_res = detail::skip_eintr([&] { return ::write(native_fd, slice.begin(), slice.size()); });
auto write_res = detail::skip_eintr([&] { return write(native_fd, slice.begin(), slice.size()); });
auto write_errno = errno;
if (write_res >= 0) {
return narrow_cast<size_t>(write_res);

View File

@ -992,7 +992,7 @@ TEST(Client, Close) {
td::thread receive_thread([&] {
auto max_continue_send = td::Random::fast_bool() ? 0 : 1000;
while (true) {
auto response = client.receive(100.0);
auto response = client.receive(10.0);
if (response.object == nullptr) {
if (!stop_send) {
stop_send = true;
@ -1056,7 +1056,7 @@ TEST(Client, ManagerClose) {
auto max_continue_send = td::Random::fast_bool() ? 0 : 1000;
bool can_stop_send = false;
while (true) {
auto response = client_manager.receive(100.0);
auto response = client_manager.receive(10.0);
if (response.object == nullptr) {
if (!stop_send) {
can_stop_send = true;