From 12665773f61785eb6b91a352f50645c10b24f17c Mon Sep 17 00:00:00 2001
From: Simon Morlat <simon.morlat@linphone.org>
Date: Fri, 23 Jun 2023 10:51:52 +0200
Subject: [PATCH] Chatroom loading optimisations. Optimize execution time of
 tests by reducing unnecessary waits.

---
 coreapi/bellesip_sal/sal_address_impl.c       | 29 ++++++++++++
 src/address/address-parser.cpp                |  3 +-
 src/address/address.cpp                       | 41 ++++++++++-------
 src/address/address.h                         |  6 +--
 src/c-wrapper/internal/c-sal.h                |  4 ++
 src/chat/notification/imdn.cpp                |  5 +++
 src/conference/conference-id.cpp              |  5 +++
 src/conference/conference-id.h                |  3 ++
 .../remote-conference-event-handler.cpp       | 16 +++----
 src/conference/participant.cpp                | 27 +++++++-----
 src/conference/participant.h                  |  6 ++-
 src/db/main-db.cpp                            | 13 +++---
 tester/call_video_tester.cpp                  |  2 +-
 tester/local_conference_tester.cpp            | 44 +++++++++----------
 tester/message_tester.c                       | 20 ++++-----
 15 files changed, 140 insertions(+), 84 deletions(-)

diff --git a/coreapi/bellesip_sal/sal_address_impl.c b/coreapi/bellesip_sal/sal_address_impl.c
index 691d2726af..526f32954a 100644
--- a/coreapi/bellesip_sal/sal_address_impl.c
+++ b/coreapi/bellesip_sal/sal_address_impl.c
@@ -334,9 +334,38 @@ bool_t sal_address_is_ipv6(const SalAddress *addr) {
 	return FALSE;
 }
 
+static inline int c_string_equal(const char *a, const char *b) {
+	if (a && b && strcmp(a, b) == 0) return TRUE;
+	if (a == NULL && b == NULL) return TRUE;
+	return FALSE;
+}
+
+int sal_address_weak_equals(const SalAddress *addr_a, const SalAddress *addr_b) {
+	belle_sip_uri_t *uri_a = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr_a));
+	belle_sip_uri_t *uri_b = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr_b));
+
+	const char *user_a = belle_sip_uri_get_user(uri_a);
+	const char *user_b = belle_sip_uri_get_user(uri_b);
+
+	if (c_string_equal(user_a, user_b)) {
+		const char *host_a = belle_sip_uri_get_host(uri_a);
+		const char *host_b = belle_sip_uri_get_host(uri_b);
+		if (c_string_equal(host_a, host_b)) {
+			return belle_sip_uri_get_port(uri_a) == belle_sip_uri_get_port(uri_b);
+		}
+	}
+	return FALSE;
+}
+
 int sal_address_equals(const SalAddress *addr_a, const SalAddress *addr_b) {
 	belle_sip_header_address_t *header_addr_a = BELLE_SIP_HEADER_ADDRESS(addr_a);
 	belle_sip_header_address_t *header_addr_b = BELLE_SIP_HEADER_ADDRESS(addr_b);
 
 	return belle_sip_header_address_equals(header_addr_a, header_addr_b);
 }
+
+int sal_address_uri_equals(const SalAddress *addr_a, const SalAddress *addr_b) {
+	belle_sip_uri_t *uri_a = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr_a));
+	belle_sip_uri_t *uri_b = belle_sip_header_address_get_uri(BELLE_SIP_HEADER_ADDRESS(addr_b));
+	return belle_sip_uri_equals(uri_a, uri_b);
+}
diff --git a/src/address/address-parser.cpp b/src/address/address-parser.cpp
index 2fc36fabdb..9d503c5ee9 100644
--- a/src/address/address-parser.cpp
+++ b/src/address/address-parser.cpp
@@ -71,8 +71,9 @@ AddressParser::AddressParser() {
 SalAddress *AddressParser::parseAddress(const string &input) {
 	size_t parsedSize;
 	SalAddress *identityAddress = (SalAddress *)mParser->parseInput("address", input, &parsedSize);
-	if (!identityAddress) {
+	if (!identityAddress || parsedSize < input.size()) {
 		lDebug() << "Unable to parse identity address from " << input;
+		if (identityAddress) sal_address_unref(identityAddress);
 		return nullptr;
 	}
 	return identityAddress;
diff --git a/src/address/address.cpp b/src/address/address.cpp
index 5ee698cb95..873cfa9de8 100644
--- a/src/address/address.cpp
+++ b/src/address/address.cpp
@@ -20,6 +20,7 @@
 
 #include <bctoolbox/defs.h>
 
+#include "address-parser.h"
 #include "belle-sip/sip-uri.h"
 
 #include "address.h"
@@ -34,30 +35,33 @@ LINPHONE_BEGIN_NAMESPACE
 
 std::unordered_map<std::string, std::unique_ptr<SalAddress, Address::SalAddressDeleter>> Address::sAddressCache;
 
-SalAddress *Address::getSalAddressFromCache(const string &uri,
-                                            std::function<SalAddress *(const std::string &)> alternateParserFunction) {
-	auto &ptr = sAddressCache[uri];
+SalAddress *Address::getSalAddressFromCache(const string &address, bool assumeGrUri) {
+	auto &ptr = sAddressCache[address];
 	if (ptr) return sal_address_clone(ptr.get());
 
-	// lInfo() << "Creating SalAddress for " << uri;
-	SalAddress *address = nullptr;
-	if (alternateParserFunction) {
-		address = alternateParserFunction(uri);
-	} else address = sal_address_new(L_STRING_TO_C(uri));
-	if (address) {
-		removeFromLeakDetector(address);
-		ptr = (unique_ptr<SalAddress, SalAddressDeleter>(address, SalAddressDeleter()));
-		return sal_address_clone(address);
+	// lInfo() << "Creating SalAddress for " << address;
+	/* To optimize, use the fast uri parser from AddressParser when we can assume that it is a simple URI with
+	 * gr param.
+	 */
+	SalAddress *parsedAddress = nullptr;
+	if (assumeGrUri) {
+		parsedAddress = AddressParser::get().parseAddress(address);
+	}
+	if (!parsedAddress) parsedAddress = sal_address_new(L_STRING_TO_C(address));
+	if (parsedAddress) {
+		removeFromLeakDetector(parsedAddress);
+		ptr = (unique_ptr<SalAddress, SalAddressDeleter>(parsedAddress, SalAddressDeleter()));
+		return sal_address_clone(parsedAddress);
 	}
 	return nullptr;
 }
 
 // -----------------------------------------------------------------------------
 
-Address::Address(const string &address) {
+Address::Address(const string &address, bool assumeGrUri) {
 	if (address.empty()) {
 		mImpl = sal_address_new_empty();
-	} else if (!(mImpl = getSalAddressFromCache(address, nullptr))) {
+	} else if (!(mImpl = getSalAddressFromCache(address, assumeGrUri))) {
 		lWarning() << "Cannot create Address, bad uri [" << address << "]";
 	}
 }
@@ -76,7 +80,7 @@ Address::Address() {
 	mImpl = sal_address_new_empty();
 }
 
-Address::Address(Address &&other) {
+Address::Address(Address &&other) : bellesip::HybridObject<LinphoneAddress, Address>(std::move(other)) {
 	mImpl = other.mImpl;
 	other.mImpl = nullptr;
 }
@@ -348,8 +352,11 @@ std::string Address::asStringUriOnly() const {
 }
 
 bool Address::weakEqual(const Address &address) const {
-	return getUsername() == address.getUsername() && getDomain() == address.getDomain() &&
-	       getPort() == address.getPort();
+	return !!sal_address_weak_equals(mImpl, address.mImpl);
+}
+
+bool Address::uriEqual(const Address &other) const {
+	return !!sal_address_uri_equals(mImpl, other.mImpl);
 }
 
 const char *Address::getHeaderValueCstr(const string &headerName) const {
diff --git a/src/address/address.h b/src/address/address.h
index c83055bd39..fca37ac571 100644
--- a/src/address/address.h
+++ b/src/address/address.h
@@ -39,7 +39,7 @@ LINPHONE_BEGIN_NAMESPACE
  */
 class LINPHONE_PUBLIC Address : public bellesip::HybridObject<LinphoneAddress, Address> {
 public:
-	explicit Address(const std::string &address);
+	explicit Address(const std::string &address, bool assumeGrUri = false);
 	Address();
 	Address(Address &&other);
 	Address(const Address &other);
@@ -135,6 +135,7 @@ public:
 
 	bool clean();
 	bool weakEqual(const Address &other) const;
+	bool uriEqual(const Address &other) const;
 
 	inline const SalAddress *getImpl() const {
 		return mImpl;
@@ -144,8 +145,7 @@ public:
 	static void clearSipAddressesCache();
 
 protected:
-	static SalAddress *getSalAddressFromCache(const std::string &uri,
-	                                          std::function<SalAddress *(const std::string &)> alternateParserFunction);
+	static SalAddress *getSalAddressFromCache(const std::string &address, bool assumeGrUri);
 
 private:
 	SalAddress *mImpl = nullptr;
diff --git a/src/c-wrapper/internal/c-sal.h b/src/c-wrapper/internal/c-sal.h
index eed4755153..53f2b49796 100644
--- a/src/c-wrapper/internal/c-sal.h
+++ b/src/c-wrapper/internal/c-sal.h
@@ -201,6 +201,10 @@ void sal_address_set_header(SalAddress *addr, const char *header_name, const cha
 const char *sal_address_get_header(const SalAddress *addr, const char *name);
 
 int sal_address_equals(const SalAddress *addr_a, const SalAddress *addr_b);
+/* comparison of user, host, port only */
+int sal_address_weak_equals(const SalAddress *addr_a, const SalAddress *addr_b);
+/* comparison of uri part only */
+int sal_address_uri_equals(const SalAddress *addr_a, const SalAddress *addr_b);
 
 void sal_address_clean_params(const SalAddress *addr);
 
diff --git a/src/chat/notification/imdn.cpp b/src/chat/notification/imdn.cpp
index 1248c7be7d..e57af42c9e 100644
--- a/src/chat/notification/imdn.cpp
+++ b/src/chat/notification/imdn.cpp
@@ -374,6 +374,11 @@ LinphoneProxyConfig *Imdn::getRelatedProxyConfig() {
 }
 
 void Imdn::send() {
+	if (deliveredMessages.empty() && displayedMessages.empty() && nonDeliveredMessages.empty()) {
+		/* nothing to do */
+		return;
+	}
+
 	try {
 		if (!chatRoom->getCore()->getCCore()->send_imdn_if_unregistered) {
 			LinphoneProxyConfig *cfg = getRelatedProxyConfig();
diff --git a/src/conference/conference-id.cpp b/src/conference/conference-id.cpp
index 5188957267..08e543d786 100644
--- a/src/conference/conference-id.cpp
+++ b/src/conference/conference-id.cpp
@@ -30,6 +30,11 @@ LINPHONE_BEGIN_NAMESPACE
 ConferenceId::ConferenceId() {
 }
 
+ConferenceId::ConferenceId(Address &&peerAddress, Address &&localAddress) {
+	this->peerAddress = Address::create(std::move(peerAddress));
+	this->localAddress = Address::create(std::move(localAddress));
+}
+
 ConferenceId::ConferenceId(const std::shared_ptr<Address> &peerAddress,
                            const std::shared_ptr<const Address> &localAddress) {
 	this->peerAddress = (peerAddress) ? Address::create(peerAddress->getUri()) : nullptr;
diff --git a/src/conference/conference-id.h b/src/conference/conference-id.h
index df21fd5b73..0aa522d196 100644
--- a/src/conference/conference-id.h
+++ b/src/conference/conference-id.h
@@ -30,6 +30,9 @@ LINPHONE_BEGIN_NAMESPACE
 class LINPHONE_PUBLIC ConferenceId {
 public:
 	ConferenceId();
+	// Caution: this optimized constructor does not care about extracting the URI part only. Use it for URI only
+	// Address.
+	ConferenceId(Address &&peerAddress, Address &&localAddress);
 	ConferenceId(const std::shared_ptr<Address> &peerAddress, const std::shared_ptr<const Address> &localAddress);
 	ConferenceId(const std::shared_ptr<Address> &peerAddress, const std::shared_ptr<Address> &localAddress);
 	ConferenceId(const ConferenceId &other);
diff --git a/src/conference/handlers/remote-conference-event-handler.cpp b/src/conference/handlers/remote-conference-event-handler.cpp
index 59ceab1dc8..5550e34843 100644
--- a/src/conference/handlers/remote-conference-event-handler.cpp
+++ b/src/conference/handlers/remote-conference-event-handler.cpp
@@ -647,28 +647,26 @@ bool RemoteConferenceEventHandler::alreadySubscribed() const {
 void RemoteConferenceEventHandler::subscribe() {
 	if (!alreadySubscribed()) return; // Already subscribed or application did not request subscription
 
-	const string &localAddress = getConferenceId().getLocalAddress()->toString();
-	LinphoneAddress *lAddr = linphone_address_new(localAddress.c_str());
+	const auto localAddress = getConferenceId().getLocalAddress();
 
 	LinphoneCore *lc = conf->getCore()->getCCore();
-	LinphoneProxyConfig *cfg = linphone_core_lookup_proxy_by_identity(lc, lAddr);
+	LinphoneAccount *acc = linphone_core_lookup_account_by_identity(lc, localAddress->toC());
 
-	if (!cfg || (linphone_proxy_config_get_state(cfg) != LinphoneRegistrationOk)) {
-		linphone_address_unref(lAddr);
+	if (!acc || (linphone_account_get_state(acc) != LinphoneRegistrationOk)) {
 		return;
 	}
 
 	const auto &peerAddress = getConferenceId().getPeerAddress();
 	ev = dynamic_pointer_cast<EventSubscribe>(
-	    (new EventSubscribe(conf->getCore(), peerAddress, cfg, "conference", 600))->toSharedPtr());
-	ev->getOp()->setFrom(localAddress);
+	    (new EventSubscribe(conf->getCore(), peerAddress, Account::toCpp(acc)->getConfig(), "conference", 600))
+	        ->toSharedPtr());
+	ev->getOp()->setFromAddress(localAddress->getImpl());
 	setInitialSubscriptionUnderWayFlag(true);
 	const string &lastNotifyStr = Utils::toString(getLastNotify());
 	ev->addCustomHeader("Last-Notify-Version", lastNotifyStr.c_str());
-	linphone_address_unref(lAddr);
 	ev->setInternal(true);
 	ev->setProperty("event-handler-private", this);
-	lInfo() << localAddress << " is subscribing to chat room or conference: " << *peerAddress
+	lInfo() << *localAddress << " is subscribing to chat room or conference: " << *peerAddress
 	        << " with last notify: " << lastNotifyStr;
 	ev->send(nullptr);
 }
diff --git a/src/conference/participant.cpp b/src/conference/participant.cpp
index 7492fbd82a..7bed6c7c26 100644
--- a/src/conference/participant.cpp
+++ b/src/conference/participant.cpp
@@ -44,7 +44,9 @@ Participant::Participant(Conference *conference,
 	session = callSession;
 }
 
-Participant::Participant() {
+Participant::Participant(std::shared_ptr<Address> address) : addr(address) {
+	L_ASSERT(address->getDisplayNameCstr() == nullptr);
+	L_ASSERT(!address->hasUriParam("gr"));
 }
 
 void Participant::configure(Conference *conference, const std::shared_ptr<Address> &address) {
@@ -53,10 +55,6 @@ void Participant::configure(Conference *conference, const std::shared_ptr<Addres
 	addr = identityAddress;
 }
 
-Participant::~Participant() {
-	clearDevices();
-}
-
 // =============================================================================
 
 shared_ptr<CallSession> Participant::createSession(const Conference &conference,
@@ -100,12 +98,18 @@ std::shared_ptr<ParticipantDevice> Participant::addDevice(const std::shared_ptr<
 std::shared_ptr<ParticipantDevice> Participant::addDevice(const std::shared_ptr<Address> &gruu, const string &name) {
 	shared_ptr<ParticipantDevice> device = findDevice(gruu, false);
 	if (device) return device;
+	/* addDevice() is intensively called during Core startup, when loading chatrooms from database.
+	 * we cannot afford to call Address:toString() for nothing when logs are disabled */
 	if (getCore() && (linphone_core_get_global_state(getCore()->getCCore()) == LinphoneGlobalOn)) {
-		lInfo() << "Add device " << (name.empty() ? "<no-name>" : name) << " with address " << gruu->toString()
-		        << " to participant " << getAddress()->toString();
+		if (bctbx_log_level_enabled(BCTBX_LOG_DOMAIN, BCTBX_LOG_MESSAGE)) {
+			lInfo() << "Add device " << (name.empty() ? "<no-name>" : name) << " with address " << gruu->toString()
+			        << " to participant " << getAddress()->toString();
+		}
 	} else {
-		lDebug() << "Add device " << (name.empty() ? "<no-name>" : name) << " with address " << gruu->toString()
-		         << " to participant " << getAddress()->toString();
+		if (bctbx_log_level_enabled(BCTBX_LOG_DOMAIN, BCTBX_LOG_DEBUG)) {
+			lDebug() << "Add device " << (name.empty() ? "<no-name>" : name) << " with address " << gruu->toString()
+			         << " to participant " << getAddress()->toString();
+		}
 	}
 	device = ParticipantDevice::create(getSharedFromThis(), gruu, name);
 	devices.push_back(device);
@@ -148,9 +152,8 @@ shared_ptr<ParticipantDevice> Participant::findDeviceBySsrc(uint32_t ssrc, Linph
 
 shared_ptr<ParticipantDevice> Participant::findDevice(const std::shared_ptr<Address> &gruu,
                                                       const bool logFailure) const {
-	const auto &it = std::find_if(devices.cbegin(), devices.cend(), [&gruu](const auto &device) {
-		return (device->getAddress()->getUri() == gruu->getUri());
-	});
+	const auto &it = std::find_if(devices.cbegin(), devices.cend(),
+	                              [&gruu](const auto &device) { return device->getAddress()->uriEqual(*gruu); });
 
 	if (it != devices.cend()) {
 		return *it;
diff --git a/src/conference/participant.h b/src/conference/participant.h
index 491845fcb5..07b1b34253 100644
--- a/src/conference/participant.h
+++ b/src/conference/participant.h
@@ -86,8 +86,10 @@ public:
 	                     const std::shared_ptr<Address> &address,
 	                     std::shared_ptr<CallSession> callSession);
 	explicit Participant(Conference *conference, const std::shared_ptr<Address> &address);
-	Participant();
-	virtual ~Participant();
+	explicit Participant(
+	    std::shared_ptr<Address> address); // acquires the address, that must be a simple URI without 'gr' parameter.
+	Participant() = default;
+	virtual ~Participant() = default;
 	// non clonable object
 	Participant *clone() const override {
 		return nullptr;
diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp
index 76e1ea2e79..91c397d6b4 100644
--- a/src/db/main-db.cpp
+++ b/src/db/main-db.cpp
@@ -4585,12 +4585,13 @@ list<shared_ptr<AbstractChatRoom>> MainDb::getChatRooms() const {
 
 		list<shared_ptr<AbstractChatRoom>> chatRooms;
 		shared_ptr<Core> core = getCore();
+		bool serverMode = linphone_core_conference_server_enabled(core->getCCore());
 
 		soci::session *session = d->dbSession.getBackendSession();
 
 		soci::rowset<soci::row> rows = (session->prepare << query);
 		for (const auto &row : rows) {
-			ConferenceId conferenceId(Address::create(row.get<string>(1)), Address::create(row.get<string>(2)));
+			ConferenceId conferenceId(Address(row.get<string>(1), true), Address(row.get<string>(2), true));
 
 			shared_ptr<AbstractChatRoom> chatRoom = core->findChatRoom(conferenceId, false);
 			if (chatRoom) {
@@ -4627,7 +4628,7 @@ list<shared_ptr<AbstractChatRoom>> MainDb::getChatRooms() const {
 				shared_ptr<Participant> me;
 				for (const auto &row : rows) {
 					shared_ptr<Participant> participant =
-					    Participant::create(nullptr, Address::create(row.get<string>(1)));
+					    Participant::create(Address::create(row.get<string>(1), true));
 					participant->setAdmin(!!row.get<int>(2));
 
 					// Fetch devices.
@@ -4640,8 +4641,8 @@ list<shared_ptr<AbstractChatRoom>> MainDb::getChatRooms() const {
 
 						soci::rowset<soci::row> rows = (session->prepare << query, soci::use(participantId));
 						for (const auto &row : rows) {
-							shared_ptr<ParticipantDevice> device =
-							    participant->addDevice(Address::create(row.get<string>(0)), row.get<string>(2, ""));
+							shared_ptr<ParticipantDevice> device = participant->addDevice(
+							    Address::create(row.get<string>(0), true), row.get<string>(2, ""));
 							device->setState(ParticipantDevice::State(static_cast<unsigned int>(row.get<int>(1, 0))));
 						}
 					}
@@ -4654,7 +4655,7 @@ list<shared_ptr<AbstractChatRoom>> MainDb::getChatRooms() const {
 				}
 
 				Conference *conference = nullptr;
-				if (!linphone_core_conference_server_enabled(core->getCCore())) {
+				if (!serverMode) {
 					bool hasBeenLeft = !!row.get<int>(8, 0);
 					if (!me) {
 						lError() << "Unable to find me in: (peer=" +
@@ -4682,7 +4683,7 @@ list<shared_ptr<AbstractChatRoom>> MainDb::getChatRooms() const {
 						soci::rowset<soci::row> rows = (session->prepare << query, soci::use(dbChatRoomId));
 						for (const auto &row : rows) {
 							ConferenceId previousId =
-							    ConferenceId(Address::create(row.get<string>(0)), conferenceId.getLocalAddress());
+							    ConferenceId(Address::create(row.get<string>(0), true), conferenceId.getLocalAddress());
 							if (previousId != conferenceId) {
 								lInfo() << "Keeping around previous chat room ID [" << previousId
 								        << "] in case BYE is received for exhumed chat room [" << conferenceId << "]";
diff --git a/tester/call_video_tester.cpp b/tester/call_video_tester.cpp
index 678c5ec820..1272b00eed 100644
--- a/tester/call_video_tester.cpp
+++ b/tester/call_video_tester.cpp
@@ -985,7 +985,7 @@ static void video_call_established_by_reinvite_with_implicit_avpf(void) {
 	LinphoneCall *caller_call, *callee_call;
 	LinphoneCallParams *params;
 	VideoStream *vstream;
-	char *record_file = bc_tester_file("avrecord.mkv");
+	char *record_file = bc_tester_file((generateRandomFilename("avrecord") + ".mkv").c_str());
 
 	policy.automatically_initiate = FALSE;
 	policy.automatically_accept = FALSE;
diff --git a/tester/local_conference_tester.cpp b/tester/local_conference_tester.cpp
index 47e79ada03..b15af74f95 100644
--- a/tester/local_conference_tester.cpp
+++ b/tester/local_conference_tester.cpp
@@ -1622,7 +1622,7 @@ static void group_chat_room_bulk_notify_to_participant(void) {
 		                             initialMarieStats.number_of_participants_added + 1,
 		                             liblinphone_tester_sip_timeout));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &pauline.getStats().number_of_participants_added,
-		                              initialPaulineStats.number_of_participants_added + 1, 5000));
+		                              initialPaulineStats.number_of_participants_added + 1, 3000));
 		BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_participants_added,
 		                             initialMichelleStats.number_of_participants_added + 1,
 		                             liblinphone_tester_sip_timeout));
@@ -1630,7 +1630,7 @@ static void group_chat_room_bulk_notify_to_participant(void) {
 		                             initialMarieStats.number_of_participant_devices_added + 1,
 		                             liblinphone_tester_sip_timeout));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &pauline.getStats().number_of_participant_devices_added,
-		                              initialPaulineStats.number_of_participant_devices_added + 1, 5000));
+		                              initialPaulineStats.number_of_participant_devices_added + 1, 3000));
 		BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_participant_devices_added,
 		                             initialMichelleStats.number_of_participant_devices_added + 1,
 		                             liblinphone_tester_sip_timeout));
@@ -1655,7 +1655,7 @@ static void group_chat_room_bulk_notify_to_participant(void) {
 		BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_subject_changed,
 		                             initialMarieStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &pauline.getStats().number_of_subject_changed,
-		                              initialPaulineStats.number_of_subject_changed + 1, 5000));
+		                              initialPaulineStats.number_of_subject_changed + 1, 3000));
 		BC_ASSERT_TRUE(wait_for_list(coresList, &laure.getStats().number_of_subject_changed,
 		                             initialLaureStats.number_of_subject_changed + 1, liblinphone_tester_sip_timeout));
 		BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_subject_changed,
@@ -1703,7 +1703,7 @@ static void group_chat_room_bulk_notify_to_participant(void) {
 		                             initialMarieStats.number_of_participant_devices_removed + 1,
 		                             liblinphone_tester_sip_timeout));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &pauline.getStats().number_of_participant_devices_removed,
-		                              initialPaulineStats.number_of_participant_devices_removed + 1, 5000));
+		                              initialPaulineStats.number_of_participant_devices_removed + 1, 3000));
 		BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_participant_devices_removed,
 		                             initialMichelleStats.number_of_participant_devices_removed + 1,
 		                             liblinphone_tester_sip_timeout));
@@ -1711,7 +1711,7 @@ static void group_chat_room_bulk_notify_to_participant(void) {
 		                             initialMarieStats.number_of_participants_removed + 1,
 		                             liblinphone_tester_sip_timeout));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &pauline.getStats().number_of_participants_removed,
-		                              initialPaulineStats.number_of_participants_removed + 1, 5000));
+		                              initialPaulineStats.number_of_participants_removed + 1, 3000));
 		BC_ASSERT_TRUE(wait_for_list(coresList, &michelle.getStats().number_of_participants_removed,
 		                             initialMichelleStats.number_of_participants_removed + 1,
 		                             liblinphone_tester_sip_timeout));
@@ -3777,21 +3777,21 @@ static void group_chat_room_add_participant_with_invalid_address(void) {
 		BC_ASSERT_FALSE(wait_for_list(coresList, &marie.getStats().number_of_participants_added,
 		                              initialMarieStats.number_of_participants_added + 1, 5000));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &marie.getStats().number_of_participant_devices_added,
-		                              initialMarieStats.number_of_participant_devices_added + 1, 5000));
+		                              initialMarieStats.number_of_participant_devices_added + 1, 1000));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &marie.getStats().number_of_participant_devices_joined,
-		                              initialMarieStats.number_of_participant_devices_joined + 1, 5000));
+		                              initialMarieStats.number_of_participant_devices_joined + 1, 1000));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &pauline.getStats().number_of_participants_added,
-		                              initialPaulineStats.number_of_participants_added + 1, 5000));
+		                              initialPaulineStats.number_of_participants_added + 1, 1000));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &pauline.getStats().number_of_participant_devices_added,
-		                              initialPaulineStats.number_of_participant_devices_added + 1, 5000));
+		                              initialPaulineStats.number_of_participant_devices_added + 1, 1000));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &pauline.getStats().number_of_participant_devices_joined,
-		                              initialPaulineStats.number_of_participant_devices_joined + 1, 5000));
+		                              initialPaulineStats.number_of_participant_devices_joined + 1, 1000));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &michelle.getStats().number_of_participants_added,
-		                              initialMichelleStats.number_of_participants_added + 1, 5000));
+		                              initialMichelleStats.number_of_participants_added + 1, 1000));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &michelle.getStats().number_of_participant_devices_added,
-		                              initialMichelleStats.number_of_participant_devices_added + 1, 5000));
+		                              initialMichelleStats.number_of_participant_devices_added + 1, 1000));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &michelle.getStats().number_of_participant_devices_joined,
-		                              initialMichelleStats.number_of_participant_devices_joined + 1, 5000));
+		                              initialMichelleStats.number_of_participant_devices_joined + 1, 1000));
 
 		BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(marieCr), 2, int, "%d");
 		BC_ASSERT_EQUAL(linphone_chat_room_get_nb_participants(paulineCr), 2, int, "%d");
@@ -3857,9 +3857,9 @@ static void group_chat_room_with_only_participant_with_invalid_address(void) {
 
 		// Check that the chat room has not been created
 		BC_ASSERT_FALSE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneConferenceStateCreated,
-		                              initialMarieStats.number_of_LinphoneConferenceStateCreated + 1, 5000));
+		                              initialMarieStats.number_of_LinphoneConferenceStateCreated + 1, 3000));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneChatRoomConferenceJoined,
-		                              initialMarieStats.number_of_LinphoneChatRoomConferenceJoined + 1, 5000));
+		                              initialMarieStats.number_of_LinphoneChatRoomConferenceJoined + 1, 1000));
 		BC_ASSERT_TRUE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneConferenceStateCreationFailed,
 		                             initialMarieStats.number_of_LinphoneConferenceStateCreationFailed + 1,
 		                             liblinphone_tester_sip_timeout));
@@ -3930,7 +3930,7 @@ static void one_to_one_chatroom_exhumed_while_offline(void) {
 		                             initialMarieStats.number_of_LinphoneMessageSent + 1,
 		                             liblinphone_tester_sip_timeout));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &pauline.getStats().number_of_LinphoneMessageReceived,
-		                              initialPaulineStats.number_of_LinphoneMessageReceived + 1, 5000));
+		                              initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000));
 		linphone_chat_message_unref(marieMsg1);
 
 		int marieMsgs = linphone_chat_room_get_history_size(marieCr);
@@ -5673,7 +5673,7 @@ static void set_video_settings_in_conference(LinphoneCoreManager *focus,
 				BC_ASSERT_FALSE(wait_for_list(
 				    coresList, &mgr->stat.number_of_participant_devices_media_capability_changed,
 				    participants_initial_stats[counter].number_of_participant_devices_media_capability_changed + 1,
-				    10000));
+				    5000));
 			} else {
 				BC_ASSERT_TRUE(wait_for_list(
 				    coresList, &mgr->stat.number_of_participant_devices_media_capability_changed,
@@ -5697,7 +5697,7 @@ static void set_video_settings_in_conference(LinphoneCoreManager *focus,
 	                             liblinphone_tester_sip_timeout));
 	if ((previous_enable_video == enable) && (!enable)) {
 		BC_ASSERT_FALSE(wait_for_list(coresList, &focus->stat.number_of_participant_devices_media_capability_changed,
-		                              focus_stat.number_of_participant_devices_media_capability_changed + 1, 10000));
+		                              focus_stat.number_of_participant_devices_media_capability_changed + 1, 3000));
 	} else {
 		BC_ASSERT_TRUE(wait_for_list(coresList, &focus->stat.number_of_participant_devices_media_capability_changed,
 		                             focus_stat.number_of_participant_devices_media_capability_changed + 1,
@@ -9339,11 +9339,9 @@ static void create_simple_conference_dial_out_organizer_codec_mismatch(void) {
 		                             focus_stat.number_of_LinphoneConferenceStateCreationFailed + 1,
 		                             liblinphone_tester_sip_timeout));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &marie.getStats().number_of_LinphoneConferenceStateCreated,
-		                              marie_stat.number_of_LinphoneConferenceStateCreated + 1,
-		                              liblinphone_tester_sip_timeout));
+		                              marie_stat.number_of_LinphoneConferenceStateCreated + 1, 3000));
 		BC_ASSERT_FALSE(wait_for_list(coresList, &focus.getStats().number_of_LinphoneCallIncomingReceived,
-		                              focus_stat.number_of_LinphoneCallIncomingReceived + 1,
-		                              liblinphone_tester_sip_timeout));
+		                              focus_stat.number_of_LinphoneCallIncomingReceived + 1, 1000));
 
 		LinphoneConference *fconference = linphone_core_search_conference_2(focus.getLc(), confAddr);
 		BC_ASSERT_PTR_NULL(fconference);
@@ -9594,7 +9592,7 @@ static void create_simple_conference_dial_out_with_some_calls_declined_base(Linp
 			BC_ASSERT_FALSE(wait_for_list(coresList, &marie.getStats().number_of_participants_removed,
 			                              marie_stat.number_of_participants_removed + 1, 3000));
 			BC_ASSERT_FALSE(wait_for_list(coresList, &focus.getStats().number_of_participants_removed,
-			                              focus_stat.number_of_participants_removed + 1, 3000));
+			                              focus_stat.number_of_participants_removed + 1, 1000));
 		} else {
 			BC_ASSERT_TRUE(
 			    wait_for_list(coresList, &focus.getStats().number_of_LinphoneCallEnd,
diff --git a/tester/message_tester.c b/tester/message_tester.c
index 548eb48742..a7d80ceba7 100644
--- a/tester/message_tester.c
+++ b/tester/message_tester.c
@@ -392,9 +392,9 @@ void text_message_base_with_text_and_forward(LinphoneCoreManager *marie,
 						bctbx_list_free_with_data(expected_reaction_from, (bctbx_list_free_func)ms_free);
 					} else {
 						BC_ASSERT_TRUE(wait_for_until(pauline->lc, marie->lc,
-						                              &pauline->stat.number_of_LinphoneMessageReceived, 1, 1000));
-						BC_ASSERT_FALSE(wait_for(pauline->lc, marie->lc,
-						                         &pauline->stat.number_of_LinphoneReactionSentOrReceived, 1));
+						                              &pauline->stat.number_of_LinphoneMessageReceived, 1, 3000));
+						BC_ASSERT_FALSE(wait_for_until(
+						    pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneReactionSentOrReceived, 1, 3000));
 					}
 					BC_ASSERT_FALSE(wait_for_until(pauline->lc, marie->lc,
 					                               &marie->stat.number_of_LinphoneMessageDeliveredToUser, 1, 1000));
@@ -1246,7 +1246,7 @@ void transfer_message_base4(LinphoneCoreManager *marie,
 				if (linphone_factory_is_imdn_available(linphone_factory_get())) {
 					// Chat message has been markes as read but not downloaded yet, so no IMDN should be received yet
 					BC_ASSERT_FALSE(wait_for_until(pauline->lc, marie->lc,
-					                               &pauline->stat.number_of_LinphoneMessageDisplayed, 1, 5000));
+					                               &pauline->stat.number_of_LinphoneMessageDisplayed, 1, 3000));
 				}
 
 				LinphoneChatMessage *recv_msg;
@@ -1295,7 +1295,7 @@ void transfer_message_base4(LinphoneCoreManager *marie,
 					belle_http_provider_set_recv_error(linphone_core_get_http_provider(marie->lc), 0);
 					if (linphone_factory_is_imdn_available(linphone_factory_get())) {
 						BC_ASSERT_FALSE(wait_for_until(pauline->lc, marie->lc,
-						                               &pauline->stat.number_of_LinphoneMessageDisplayed, 1, 5000));
+						                               &pauline->stat.number_of_LinphoneMessageDisplayed, 1, 3000));
 					}
 				} else {
 					/* wait for a long time in case the DNS SRV resolution takes times - it should be immediate though
@@ -1338,7 +1338,7 @@ void transfer_message_base4(LinphoneCoreManager *marie,
 
 				if (linphone_factory_is_imdn_available(linphone_factory_get())) {
 					BC_ASSERT_FALSE(wait_for_until(pauline->lc, marie->lc,
-					                               &pauline->stat.number_of_LinphoneMessageDisplayed, 1, 5000));
+					                               &pauline->stat.number_of_LinphoneMessageDisplayed, 1, 3000));
 				}
 				linphone_chat_room_mark_as_read(marie_room);
 				if (linphone_factory_is_imdn_available(linphone_factory_get())) {
@@ -2631,7 +2631,7 @@ static void aggregated_imdns(void) {
 	BC_ASSERT_TRUE(wait_for(pauline->lc, marie->lc, &pauline->stat.number_of_LinphoneMessageSent, 3));
 
 	/* Marie shall not receive them */
-	BC_ASSERT_FALSE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
+	BC_ASSERT_FALSE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1, 3000));
 
 	/* Marie is now online */
 	linphone_core_set_network_reachable(marie->lc, TRUE);
@@ -3883,7 +3883,7 @@ static void received_messages_with_aggregation_enabled(void) {
 	// check message is received using only new callback when chat room is being created
 	BC_ASSERT_TRUE(
 	    wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneAggregatedMessagesReceived, 1, 5000));
-	BC_ASSERT_FALSE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
+	BC_ASSERT_FALSE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1, 3000));
 
 	linphone_chat_message_unref(chat_msg);
 	reset_counters(&pauline->stat);
@@ -3896,7 +3896,7 @@ static void received_messages_with_aggregation_enabled(void) {
 	// check message is received using only new callback for existing chat room
 	BC_ASSERT_TRUE(
 	    wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneAggregatedMessagesReceived, 1, 5000));
-	BC_ASSERT_FALSE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1));
+	BC_ASSERT_FALSE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 1, 3000));
 
 	linphone_chat_message_unref(chat_msg);
 	reset_counters(&pauline->stat);
@@ -3913,7 +3913,7 @@ static void received_messages_with_aggregation_enabled(void) {
 	// aggregation delay seconds
 	BC_ASSERT_TRUE(
 	    wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneAggregatedMessagesReceived, 10, 5000));
-	BC_ASSERT_FALSE(wait_for(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 10));
+	BC_ASSERT_FALSE(wait_for_until(pauline->lc, marie->lc, &marie->stat.number_of_LinphoneMessageReceived, 10, 3000));
 
 	// Give some time for IMDN's 200 OK to be received so it doesn't leak
 	wait_for_until(pauline->lc, marie->lc, NULL, 0, 1000);
-- 
GitLab