From 83d13e6248d7d8365a8cfcb328f04742d4bffe7a Mon Sep 17 00:00:00 2001
From: Andrea Gianarda <andrea.gianarda@belledonne-communications.com>
Date: Tue, 17 Oct 2023 11:58:06 +0200
Subject: [PATCH] - For backward compatibility, never set local and peer
 addresses of the ConferenceID object to nullptr - Clean up temporary database
 tables before starting an update because they are not deleted if the
 MainDb::updateSchema() fails - Reply 481 Transaction Does Not Exist to any
 INVITE or UPDATE received after the BYE is sent

---
 coreapi/linphonecore.c                        |  2 +-
 src/address/address.cpp                       |  4 +--
 src/c-wrapper/api/c-chat-room.cpp             |  4 +--
 src/chat/chat-room/client-group-chat-room.cpp |  4 +--
 src/conference/conference-id.cpp              | 31 +++++++++----------
 src/conference/conference-id.h                |  4 +--
 src/db/main-db.cpp                            | 28 ++++++++++++++++-
 src/sal/call-op.cpp                           |  5 ++-
 8 files changed, 55 insertions(+), 27 deletions(-)

diff --git a/coreapi/linphonecore.c b/coreapi/linphonecore.c
index 26795f7053..d9d9c07c76 100644
--- a/coreapi/linphonecore.c
+++ b/coreapi/linphonecore.c
@@ -3617,7 +3617,7 @@ static void update_primary_contact(LinphoneCore *lc) {
 	url = linphone_address_new(lc->sip_conf.contact);
 	if (!url) {
 		ms_error("Could not parse identity contact !");
-		url = linphone_address_new("sip:unknown@unkwownhost");
+		url = linphone_address_new("sip:unknown@unknownhost");
 	}
 	linphone_core_get_local_ip(lc, AF_UNSPEC, NULL, tmp);
 	if (strcmp(tmp, "127.0.0.1") == 0 || strcmp(tmp, "::1") == 0) {
diff --git a/src/address/address.cpp b/src/address/address.cpp
index c5b5ecc602..c61bc9c277 100644
--- a/src/address/address.cpp
+++ b/src/address/address.cpp
@@ -295,7 +295,7 @@ bool Address::clean() {
 }
 
 char *Address::toStringCstr() const {
-	return isValid() ? sal_address_as_string(mImpl) : nullptr;
+	return isValid() ? sal_address_as_string(mImpl) : ms_strdup("");
 }
 
 std::string Address::toString() const {
@@ -349,7 +349,7 @@ string Address::toStringOrdered() const {
 }
 
 char *Address::asStringUriOnlyCstr() const {
-	return isValid() ? sal_address_as_string_uri_only(mImpl) : nullptr;
+	return isValid() ? sal_address_as_string_uri_only(mImpl) : ms_strdup("");
 }
 
 std::string Address::asStringUriOnly() const {
diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp
index c04027b25c..fcd99398fc 100644
--- a/src/c-wrapper/api/c-chat-room.cpp
+++ b/src/c-wrapper/api/c-chat-room.cpp
@@ -102,7 +102,7 @@ LinphoneCore *linphone_chat_room_get_core(const LinphoneChatRoom *cr) {
 
 const LinphoneAddress *linphone_chat_room_get_peer_address(LinphoneChatRoom *cr) {
 	const auto &address = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getPeerAddress();
-	if (address && address->isValid()) {
+	if (address) {
 		return address->toC();
 	} else {
 		return NULL;
@@ -111,7 +111,7 @@ const LinphoneAddress *linphone_chat_room_get_peer_address(LinphoneChatRoom *cr)
 
 const LinphoneAddress *linphone_chat_room_get_local_address(LinphoneChatRoom *cr) {
 	const auto &address = L_GET_CPP_PTR_FROM_C_OBJECT(cr)->getLocalAddress();
-	if (address && address->isValid()) {
+	if (address) {
 		return address->toC();
 	} else {
 		return NULL;
diff --git a/src/chat/chat-room/client-group-chat-room.cpp b/src/chat/chat-room/client-group-chat-room.cpp
index 2258b25b7d..c1eb4044b1 100644
--- a/src/chat/chat-room/client-group-chat-room.cpp
+++ b/src/chat/chat-room/client-group-chat-room.cpp
@@ -97,10 +97,10 @@ shared_ptr<CallSession> ClientGroupChatRoomPrivate::createSessionTo(const std::s
 
 shared_ptr<CallSession> ClientGroupChatRoomPrivate::createSession() {
 	L_Q();
-	const std::shared_ptr<Address> &peerAddress(q->getConferenceId().getPeerAddress());
+	const std::shared_ptr<Address> &conferenceAddress = q->getConferenceAddress();
 	shared_ptr<Participant> &focus = static_pointer_cast<RemoteConference>(q->getConference())->focus;
 	const std::shared_ptr<Address> sessionTo =
-	    (peerAddress && peerAddress->isValid()) ? peerAddress : focus->getAddress();
+	    (conferenceAddress && conferenceAddress->isValid()) ? conferenceAddress : focus->getAddress();
 	return createSessionTo(sessionTo);
 }
 
diff --git a/src/conference/conference-id.cpp b/src/conference/conference-id.cpp
index 08e543d786..1f891f1f33 100644
--- a/src/conference/conference-id.cpp
+++ b/src/conference/conference-id.cpp
@@ -30,20 +30,19 @@ 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(Address &&pAddress, Address &&lAddress) {
+	peerAddress = Address::create(std::move(pAddress));
+	localAddress = Address::create(std::move(lAddress));
 }
 
-ConferenceId::ConferenceId(const std::shared_ptr<Address> &peerAddress,
-                           const std::shared_ptr<const Address> &localAddress) {
-	this->peerAddress = (peerAddress) ? Address::create(peerAddress->getUri()) : nullptr;
-	this->localAddress = (localAddress) ? Address::create(localAddress->getUri()) : nullptr;
+ConferenceId::ConferenceId(const std::shared_ptr<Address> &pAddress, const std::shared_ptr<const Address> &lAddress) {
+	setPeerAddress(pAddress);
+	setLocalAddress(lAddress);
 }
 
-ConferenceId::ConferenceId(const std::shared_ptr<Address> &peerAddress, const std::shared_ptr<Address> &localAddress) {
-	this->peerAddress = (peerAddress) ? Address::create(peerAddress->getUri()) : nullptr;
-	this->localAddress = (localAddress) ? Address::create(localAddress->getUri()) : nullptr;
+ConferenceId::ConferenceId(const std::shared_ptr<Address> &pAddress, const std::shared_ptr<Address> &lAddress) {
+	setPeerAddress(pAddress);
+	setLocalAddress(lAddress);
 }
 
 ConferenceId::ConferenceId(const ConferenceId &other)
@@ -51,8 +50,8 @@ ConferenceId::ConferenceId(const ConferenceId &other)
 }
 
 ConferenceId &ConferenceId::operator=(const ConferenceId &other) {
-	this->peerAddress = other.peerAddress;
-	this->localAddress = other.localAddress;
+	peerAddress = other.peerAddress;
+	localAddress = other.localAddress;
 	return *this;
 }
 
@@ -70,12 +69,12 @@ bool ConferenceId::operator<(const ConferenceId &other) const {
 	       (*peerAddress == *(other.peerAddress) && *localAddress < *(other.localAddress));
 }
 
-void ConferenceId::setPeerAddress(const std::shared_ptr<Address> &addr) {
-	peerAddress = addr;
+void ConferenceId::setPeerAddress(const std::shared_ptr<const Address> &addr) {
+	peerAddress = (addr) ? Address::create(addr->getUri()) : Address::create();
 }
 
-void ConferenceId::setLocalAddress(const std::shared_ptr<Address> &addr) {
-	localAddress = addr;
+void ConferenceId::setLocalAddress(const std::shared_ptr<const Address> &addr) {
+	localAddress = (addr) ? Address::create(addr->getUri()) : Address::create();
 }
 
 const std::shared_ptr<Address> &ConferenceId::getPeerAddress() const {
diff --git a/src/conference/conference-id.h b/src/conference/conference-id.h
index 0aa522d196..4134e118ac 100644
--- a/src/conference/conference-id.h
+++ b/src/conference/conference-id.h
@@ -53,8 +53,8 @@ public:
 	const std::shared_ptr<Address> &getPeerAddress() const;
 	const std::shared_ptr<Address> &getLocalAddress() const;
 
-	void setPeerAddress(const std::shared_ptr<Address> &addr);
-	void setLocalAddress(const std::shared_ptr<Address> &addr);
+	void setPeerAddress(const std::shared_ptr<const Address> &addr);
+	void setLocalAddress(const std::shared_ptr<const Address> &addr);
 
 	bool isValid() const;
 
diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp
index 44aac9ee19..0745bd2ef0 100644
--- a/src/db/main-db.cpp
+++ b/src/db/main-db.cpp
@@ -2477,7 +2477,28 @@ void MainDbPrivate::updateSchema() {
 		                " joining_time" +
 		                dbSession.timestampType() + " DEFAULT " + dbSession.currentTimestamp() + ") " + charset;
 
-		*session << "INSERT INTO chat_room_participant_device_clone SELECT * FROM chat_room_participant_device";
+		int idx = 0;
+		//		*session << "INSERT INTO chat_room_participant_device_clone SELECT * FROM chat_room_participant_device";
+		soci::rowset<soci::row> originalParticipantDeviceRows =
+		    (session->prepare << "SELECT chat_room_participant_id, participant_device_sip_address_id, state, name, "
+		                         "joining_method, joining_time FROM chat_room_participant_device");
+		for (const auto &row : originalParticipantDeviceRows) {
+			lInfo() << __func__ << " DEBUG DEBUG clone idx " << idx;
+			idx++;
+			const auto participantId = dbSession.resolveId(row, 0);
+			const auto deviceId = dbSession.resolveId(row, 1);
+			const auto state = row.get<int>(2);
+			const auto name = row.get<string>(3, "");
+			const auto joiningMethod = row.get<int>(4);
+			const auto joiningTime = dbSession.getTime(row, 5);
+			auto joiningTimeDb = dbSession.getTimeWithSociIndicator(joiningTime);
+			*session << "INSERT INTO chat_room_participant_device_clone (chat_room_participant_id, "
+			            "participant_device_sip_address_id, state, name, joining_method, joining_time)"
+			            " VALUES (:participantId, :participantDeviceSipAddressId, :participantDeviceState, "
+			            ":participantDeviceName, :participantDeviceJoiningMethod, :participantDeviceJoiningTime)",
+			    soci::use(participantId), soci::use(deviceId), soci::use(state), soci::use(name),
+			    soci::use(joiningMethod), soci::use(joiningTimeDb.first, joiningTimeDb.second);
+		}
 
 		*session << "DROP TABLE IF EXISTS chat_room_participant_device";
 
@@ -2507,10 +2528,13 @@ void MainDbPrivate::updateSchema() {
 		                ") " +
 		                charset;
 
+		int idx2 = 0;
 		soci::rowset<soci::row> participantDeviceRows =
 		    (session->prepare << "SELECT chat_room_participant_id, participant_device_sip_address_id, state, name, "
 		                         "joining_method, joining_time FROM chat_room_participant_device_clone");
 		for (const auto &row : participantDeviceRows) {
+			lInfo() << __func__ << " DEBUG DEBUG copy from clone idx " << idx2;
+			idx2++;
 			const auto participantId = dbSession.resolveId(row, 0);
 			const auto deviceId = dbSession.resolveId(row, 1);
 			const auto state = row.get<int>(2);
@@ -2877,6 +2901,8 @@ void MainDb::init() {
 	 * The mysql backend (used server-side) doesn't support this PRAGMA.
 	 */
 
+	initCleanup();
+
 	session->begin();
 
 	try {
diff --git a/src/sal/call-op.cpp b/src/sal/call-op.cpp
index 11f7a606dd..6a085ebbf1 100644
--- a/src/sal/call-op.cpp
+++ b/src/sal/call-op.cpp
@@ -1005,7 +1005,10 @@ void SalCallOp::processRequestEventCb(void *userCtx, const belle_sip_request_eve
 				op->callTerminated(serverTransaction, 200, request);
 				// Call end not notified by dialog deletion because transaction can end before dialog
 			} else if ((method == "INVITE") || (isUpdate = (method == "UPDATE"))) {
-				if (isUpdate && !belle_sip_message_get_body(BELLE_SIP_MESSAGE(request))) {
+				if ((op->mState == State::Terminated) || (op->mState == State::Terminating)) {
+					// A BYE has already been sent therefore we cannot accept reINVITEs or UPDATEs anymore
+					response = op->createResponseFromRequest(request, 481);
+				} else if (isUpdate && !belle_sip_message_get_body(BELLE_SIP_MESSAGE(request))) {
 					response = op->createResponseFromRequest(request, 200);
 
 					if (op->mRoot->mSessionExpiresEnabled) {
-- 
GitLab