Skip to content

Commit

Permalink
Merge pull request #4207 from nextcloud/backport/4120/stable-20.0
Browse files Browse the repository at this point in the history
[stable-20.0] Add support for federated calls
  • Loading branch information
mahibi authored Sep 13, 2024
2 parents 01d7a38 + 9fb8add commit 32ed934
Show file tree
Hide file tree
Showing 20 changed files with 291 additions and 27 deletions.
14 changes: 12 additions & 2 deletions app/src/main/java/com/nextcloud/talk/activities/CallActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -1453,7 +1453,7 @@ class CallActivity : CallBaseActivity() {
private fun fetchSignalingSettings() {
Log.d(TAG, "fetchSignalingSettings")
val apiVersion = ApiUtils.getSignalingApiVersion(conversationUser, intArrayOf(ApiUtils.API_V3, 2, 1))
ncApi!!.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(apiVersion, baseUrl))
ncApi!!.getSignalingSettings(credentials, ApiUtils.getUrlForSignalingSettings(apiVersion, baseUrl, roomToken!!))
.subscribeOn(Schedulers.io())
.retry(API_RETRIES)
.observeOn(AndroidSchedulers.mainThread())
Expand All @@ -1475,6 +1475,8 @@ class CallActivity : CallBaseActivity() {
signalingSettingsOverall.ocs!!.settings!!.externalSignalingServer
externalSignalingServer!!.externalSignalingTicket =
signalingSettingsOverall.ocs!!.settings!!.externalSignalingTicket
externalSignalingServer!!.federation =
signalingSettingsOverall.ocs!!.settings!!.federation
hasExternalSignalingServer = true
} else {
hasExternalSignalingServer = false
Expand Down Expand Up @@ -1630,7 +1632,9 @@ class CallActivity : CallBaseActivity() {

private fun callOrJoinRoomViaWebSocket() {
if (hasExternalSignalingServer) {
webSocketClient!!.joinRoomWithRoomTokenAndSession(roomToken!!, callSession)
webSocketClient!!.joinRoomWithRoomTokenAndSession(
roomToken!!, callSession, externalSignalingServer!!.federation
)
} else {
performCall()
}
Expand Down Expand Up @@ -2157,6 +2161,10 @@ class CallActivity : CallBaseActivity() {
Log.d(TAG, " newSession joined: $sessionId")
addCallParticipant(sessionId)

if (participant.actorType != null && participant.actorId != null) {
callParticipants[sessionId]!!.setActor(participant.actorType, participant.actorId)
}

val userId = participant.userId
if (userId != null) {
callParticipants[sessionId]!!.setUserId(userId)
Expand Down Expand Up @@ -2510,10 +2518,12 @@ class CallActivity : CallBaseActivity() {
}
val defaultGuestNick = resources.getString(R.string.nc_nick_guest)
val participantDisplayItem = ParticipantDisplayItem(
context,
baseUrl,
defaultGuestNick,
rootEglBase,
videoStreamType,
roomToken,
callParticipantModel
)
val sessionId = callParticipantModel.sessionId
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@
*/
package com.nextcloud.talk.adapters;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;

import com.nextcloud.talk.call.CallParticipantModel;
import com.nextcloud.talk.call.RaisedHand;
import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.DisplayUtils;

import org.webrtc.EglBase;
import org.webrtc.MediaStream;
Expand All @@ -29,15 +32,21 @@ public class ParticipantDisplayItem {

private final ParticipantDisplayItemNotifier participantDisplayItemNotifier = new ParticipantDisplayItemNotifier();

private final Context context;

private final String baseUrl;
private final String defaultGuestNick;
private final EglBase rootEglBase;

private final String session;
private final String streamType;

private final String roomToken;

private final CallParticipantModel callParticipantModel;

private Participant.ActorType actorType;
private String actorId;
private String userId;
private PeerConnection.IceConnectionState iceConnectionState;
private String nick;
Expand All @@ -62,15 +71,19 @@ public void onReaction(String reaction) {
}
};

public ParticipantDisplayItem(String baseUrl, String defaultGuestNick, EglBase rootEglBase, String streamType,
CallParticipantModel callParticipantModel) {
public ParticipantDisplayItem(Context context, String baseUrl, String defaultGuestNick, EglBase rootEglBase,
String streamType, String roomToken, CallParticipantModel callParticipantModel) {
this.context = context;

this.baseUrl = baseUrl;
this.defaultGuestNick = defaultGuestNick;
this.rootEglBase = rootEglBase;

this.session = callParticipantModel.getSessionId();
this.streamType = streamType;

this.roomToken = roomToken;

this.callParticipantModel = callParticipantModel;
this.callParticipantModel.addObserver(callParticipantModelObserver, handler);

Expand All @@ -82,6 +95,8 @@ public void destroy() {
}

private void updateFromModel() {
actorType = callParticipantModel.getActorType();
actorId = callParticipantModel.getActorId();
userId = callParticipantModel.getUserId();
nick = callParticipantModel.getNick();

Expand All @@ -107,7 +122,10 @@ private void updateFromModel() {
}

private void updateUrlForAvatar() {
if (!TextUtils.isEmpty(userId)) {
if (actorType == Participant.ActorType.FEDERATED) {
int darkTheme = DisplayUtils.INSTANCE.isDarkModeOn(context) ? 1 : 0;
urlForAvatar = ApiUtils.getUrlForFederatedAvatar(baseUrl, roomToken, actorId, darkTheme, true);
} else if (!TextUtils.isEmpty(userId)) {
urlForAvatar = ApiUtils.getUrlForAvatar(baseUrl, userId, true);
} else {
urlForAvatar = ApiUtils.getUrlForGuestAvatar(baseUrl, getNick(), true);
Expand Down Expand Up @@ -166,6 +184,8 @@ public void removeObserver(Observer observer) {
public String toString() {
return "ParticipantSession{" +
"userId='" + userId + '\'' +
", actorType='" + actorType + '\'' +
", actorId='" + actorId + '\'' +
", session='" + session + '\'' +
", nick='" + nick + '\'' +
", urlForAvatar='" + urlForAvatar + '\'' +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package com.nextcloud.talk.call;

import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.signaling.SignalingMessageReceiver;
import com.nextcloud.talk.webrtc.PeerConnectionWrapper;

Expand Down Expand Up @@ -132,6 +133,10 @@ public CallParticipantModel getCallParticipantModel() {
return callParticipantModel;
}

public void setActor(Participant.ActorType actorType, String actorId) {
callParticipantModel.setActor(actorType, actorId);
}

public void setUserId(String userId) {
callParticipantModel.setUserId(userId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ public void onAllParticipantsUpdate(long inCall) {

private Participant copyParticipant(Participant participant) {
Participant copiedParticipant = new Participant();
copiedParticipant.setActorId(participant.getActorId());
copiedParticipant.setActorType(participant.getActorType());
copiedParticipant.setInCall(participant.getInCall());
copiedParticipant.setInternal(participant.getInternal());
copiedParticipant.setLastPing(participant.getLastPing());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

import android.os.Handler;

import com.nextcloud.talk.models.json.participants.Participant;

import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;

Expand All @@ -25,6 +27,8 @@
*
* Audio and video in screen shares, on the other hand, are always seen as available.
*
* Actor type and actor id will be set only in Talk >= 20.
*
* Clients of the model can observe it with CallParticipantModel.Observer to be notified when any value changes.
* Getters called after receiving a notification are guaranteed to provide at least the value that triggered the
* notification, but it may return even a more up to date one (so getting the value again on the following
Expand All @@ -39,6 +43,8 @@ public class CallParticipantModel {

protected final String sessionId;

protected Data<Participant.ActorType> actorType;
protected Data<String> actorId;
protected Data<String> userId;
protected Data<String> nick;

Expand Down Expand Up @@ -81,6 +87,8 @@ public void setValue(T value) {
public CallParticipantModel(String sessionId) {
this.sessionId = sessionId;

this.actorType = new Data<>();
this.actorId = new Data<>();
this.userId = new Data<>();
this.nick = new Data<>();

Expand All @@ -101,6 +109,14 @@ public String getSessionId() {
return sessionId;
}

public Participant.ActorType getActorType() {
return actorType.getValue();
}

public String getActorId() {
return actorId.getValue();
}

public String getUserId() {
return userId.getValue();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
*/
package com.nextcloud.talk.call;

import com.nextcloud.talk.models.json.participants.Participant;

import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;

Expand All @@ -20,6 +22,11 @@ public MutableCallParticipantModel(String sessionId) {
super(sessionId);
}

public void setActor(Participant.ActorType actorType, String actorId) {
this.actorType.setValue(actorType);
this.actorId.setValue(actorId);
}

public void setUserId(String userId) {
this.userId.setValue(userId);
}
Expand Down
63 changes: 57 additions & 6 deletions app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,12 @@ import com.nextcloud.talk.jobs.ShareOperationWorker
import com.nextcloud.talk.jobs.UploadAndShareFilesWorker
import com.nextcloud.talk.location.LocationPickerActivity
import com.nextcloud.talk.messagesearch.MessageSearchActivity
import com.nextcloud.talk.models.ExternalSignalingServer
import com.nextcloud.talk.models.domain.ConversationModel
import com.nextcloud.talk.models.json.capabilities.SpreedCapability
import com.nextcloud.talk.models.json.chat.ReadStatus
import com.nextcloud.talk.models.json.conversations.ConversationEnums
import com.nextcloud.talk.models.json.signaling.settings.SignalingSettingsOverall
import com.nextcloud.talk.polls.ui.PollCreateDialogFragment
import com.nextcloud.talk.remotefilebrowser.activities.RemoteFileBrowserActivity
import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
Expand Down Expand Up @@ -177,6 +179,8 @@ import com.stfalcon.chatkit.messages.MessageHolders
import com.stfalcon.chatkit.messages.MessageHolders.ContentChecker
import com.stfalcon.chatkit.messages.MessagesListAdapter
import com.stfalcon.chatkit.utils.DateFormatter
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collect
Expand Down Expand Up @@ -302,6 +306,7 @@ class ChatActivity :

var webSocketInstance: WebSocketInstance? = null
var signalingMessageSender: SignalingMessageSender? = null
var externalSignalingServer: ExternalSignalingServer? = null

var getRoomInfoTimerHandler: Handler? = null

Expand Down Expand Up @@ -631,10 +636,12 @@ class ChatActivity :

logConversationInfos("joinRoomWithPassword#onNext")

setupWebsocket()
if (webSocketInstance != null) {
webSocketInstance?.joinRoomWithRoomTokenAndSession(
roomToken,
sessionIdAfterRoomJoined
sessionIdAfterRoomJoined,
externalSignalingServer?.federation
)
}
if (startCallFromNotification != null && startCallFromNotification) {
Expand Down Expand Up @@ -952,7 +959,6 @@ class ChatActivity :

pullChatMessagesPending = false

setupWebsocket()
webSocketInstance?.getSignalingMessageReceiver()?.addListener(localParticipantMessageListener)
webSocketInstance?.getSignalingMessageReceiver()?.addListener(conversationMessageListener)

Expand Down Expand Up @@ -2391,10 +2397,12 @@ class ChatActivity :
} else {
Log.d(TAG, "sessionID was valid -> skip joinRoom")

setupWebsocket()
if (webSocketInstance != null) {
webSocketInstance?.joinRoomWithRoomTokenAndSession(
roomToken,
sessionIdAfterRoomJoined
sessionIdAfterRoomJoined,
externalSignalingServer?.federation
)
}
}
Expand Down Expand Up @@ -2423,16 +2431,59 @@ class ChatActivity :
}

private fun setupWebsocket() {
if (conversationUser == null) {
if (currentConversation == null || conversationUser == null) {
return
}
webSocketInstance = WebSocketConnectionHelper.getWebSocketInstanceForUser(conversationUser!!)

if (currentConversation!!.remoteServer != null) {
val apiVersion = ApiUtils.getSignalingApiVersion(conversationUser!!, intArrayOf(ApiUtils.API_V3, 2, 1))
ncApi!!.getSignalingSettings(
credentials,
ApiUtils.getUrlForSignalingSettings(apiVersion, conversationUser!!.baseUrl, roomToken!!)
).blockingSubscribe(object : Observer<SignalingSettingsOverall> {
override fun onSubscribe(d: Disposable) {
// unused atm
}

override fun onNext(signalingSettingsOverall: SignalingSettingsOverall) {
if (signalingSettingsOverall.ocs!!.settings!!.externalSignalingServer == null) {
return
}

externalSignalingServer = ExternalSignalingServer()
externalSignalingServer!!.externalSignalingServer = signalingSettingsOverall.ocs!!.settings!!
.externalSignalingServer
externalSignalingServer!!.externalSignalingTicket = signalingSettingsOverall.ocs!!.settings!!
.externalSignalingTicket
externalSignalingServer!!.federation = signalingSettingsOverall.ocs!!.settings!!.federation

webSocketInstance = WebSocketConnectionHelper.getExternalSignalingInstanceForServer(
externalSignalingServer!!.externalSignalingServer,
conversationUser,
externalSignalingServer!!.externalSignalingTicket,
TextUtils.isEmpty(credentials)
)
}

override fun onError(e: Throwable) {
Log.e(CallActivity.TAG, e.message, e)
}

override fun onComplete() {
// unused atm
}
})
} else {
webSocketInstance = WebSocketConnectionHelper.getWebSocketInstanceForUser(conversationUser!!)
}

if (webSocketInstance == null) {
Log.d(TAG, "webSocketInstance not set up. This should only happen when not using the HPB")
}

signalingMessageSender = webSocketInstance?.signalingMessageSender
webSocketInstance?.getSignalingMessageReceiver()?.addListener(localParticipantMessageListener)
webSocketInstance?.getSignalingMessageReceiver()?.addListener(conversationMessageListener)
}

private fun processCallStartedMessages(chatMessageList: List<ChatMessage>) {
Expand Down Expand Up @@ -3190,7 +3241,7 @@ class ChatActivity :
val lon = data["longitude"]!!
metaData =
"{\"type\":\"geo-location\",\"id\":\"geo:$lat,$lon\",\"latitude\":\"$lat\"," +
"\"longitude\":\"$lon\",\"name\":\"$name\"}"
"\"longitude\":\"$lon\",\"name\":\"$name\"}"
}

when (type) {
Expand Down
Loading

0 comments on commit 32ed934

Please sign in to comment.