davidliu
Committed by GitHub

Add rpc handler methods to Room class for convenience (#663)

---
"client-sdk-android": patch
---
Add rpc handler methods to Room class for convenience.
... ...
... ... @@ -47,6 +47,7 @@ import io.livekit.android.room.metrics.collectMetrics
import io.livekit.android.room.network.NetworkCallbackManagerFactory
import io.livekit.android.room.participant.*
import io.livekit.android.room.provisions.LKObjects
import io.livekit.android.room.rpc.RpcManager
import io.livekit.android.room.track.*
import io.livekit.android.room.types.toSDKType
import io.livekit.android.room.util.ConnectionWarmer
... ... @@ -69,6 +70,7 @@ import livekit.org.webrtc.audio.AudioDeviceModule
import java.net.URI
import java.util.Date
import javax.inject.Named
import kotlin.time.Duration
class Room
@AssistedInject
... ... @@ -108,7 +110,7 @@ constructor(
private val connectionWarmer: ConnectionWarmer,
private val audioRecordPrewarmer: AudioRecordPrewarmer,
private val incomingDataStreamManager: IncomingDataStreamManager,
) : RTCEngine.Listener, ParticipantListener, IncomingDataStreamManager by incomingDataStreamManager {
) : RTCEngine.Listener, ParticipantListener, RpcManager, IncomingDataStreamManager by incomingDataStreamManager {
private lateinit var coroutineScope: CoroutineScope
private val eventBus = BroadcastEventBus<RoomEvent>()
... ... @@ -1040,6 +1042,19 @@ constructor(
},
)
// ----------------------------------- RpcManager ------------------------------------//
override suspend fun registerRpcMethod(method: String, handler: RpcHandler) {
localParticipant.registerRpcMethod(method, handler)
}
override fun unregisterRpcMethod(method: String) {
localParticipant.unregisterRpcMethod(method)
}
override suspend fun performRpc(destinationIdentity: Participant.Identity, method: String, payload: String, responseTimeout: Duration): String {
return localParticipant.performRpc(destinationIdentity, method, payload, responseTimeout)
}
// ----------------------------------- RTCEngine.Listener ------------------------------------//
/**
... ...
... ... @@ -109,7 +109,9 @@ internal constructor(
@Named(InjectionNames.SENDER)
private val capabilitiesGetter: CapabilitiesGetter,
private val outgoingDataStreamManager: OutgoingDataStreamManager,
) : Participant(Sid(""), null, coroutineDispatcher), OutgoingDataStreamManager by outgoingDataStreamManager {
) : Participant(Sid(""), null, coroutineDispatcher),
OutgoingDataStreamManager by outgoingDataStreamManager,
RpcManager {
var audioTrackCaptureDefaults: LocalAudioTrackOptions by defaultsManager::audioTrackCaptureDefaults
var audioTrackPublishDefaults: AudioTrackPublishDefaults by defaultsManager::audioTrackPublishDefaults
... ... @@ -988,7 +990,7 @@ internal constructor(
* @see performRpc
*/
@Suppress("RedundantSuspendModifier")
suspend fun registerRpcMethod(
override suspend fun registerRpcMethod(
method: String,
handler: RpcHandler,
) {
... ... @@ -1000,7 +1002,7 @@ internal constructor(
*
* @param method The name of the RPC method to unregister
*/
fun unregisterRpcMethod(
override fun unregisterRpcMethod(
method: String,
) {
this.rpcHandlers.remove(method)
... ... @@ -1056,11 +1058,11 @@ internal constructor(
* @return The response payload.
* @throws RpcError on failure. Details in [RpcError.message].
*/
suspend fun performRpc(
override suspend fun performRpc(
destinationIdentity: Identity,
method: String,
payload: String,
responseTimeout: Duration = 10.seconds,
responseTimeout: Duration,
): String = coroutineScope {
val maxRoundTripLatency = 2.seconds
... ...
... ... @@ -16,8 +16,78 @@
package io.livekit.android.room.rpc
class RpcManager {
import io.livekit.android.room.participant.Participant.Identity
import io.livekit.android.room.participant.RpcHandler
import io.livekit.android.room.participant.RpcInvocationData
import io.livekit.android.rpc.RpcError
import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds
interface RpcManager {
companion object {
const val RPC_VERSION = 1
}
/**
* Establishes the participant as a receiver for calls of the specified RPC method.
* Will overwrite any existing callback for the same method.
*
* Example:
* ```kt
* room.registerRpcMethod("greet") { (requestId, callerIdentity, payload, responseTimeout) ->
* Log.i("TAG", "Received greeting from ${callerIdentity}: ${payload}")
*
* // Return a string
* "Hello, ${callerIdentity}!"
* }
* ```
*
* The handler receives an [RpcInvocationData] with the following parameters:
* - `requestId`: A unique identifier for this RPC request
* - `callerIdentity`: The identity of the RemoteParticipant who initiated the RPC call
* - `payload`: The data sent by the caller (as a string)
* - `responseTimeout`: The maximum time available to return a response
*
* The handler should return a string.
* If unable to respond within [RpcInvocationData.responseTimeout], the request will result in an error on the caller's side.
*
* You may throw errors of type [RpcError] with a string `message` in the handler,
* and they will be received on the caller's side with the message intact.
* Other errors thrown in your handler will not be transmitted as-is, and will instead arrive to the caller as `1500` ("Application Error").
*
* @param method The name of the indicated RPC method
* @param handler Will be invoked when an RPC request for this method is received
* @see RpcHandler
* @see RpcInvocationData
* @see performRpc
*/
@Suppress("RedundantSuspendModifier")
suspend fun registerRpcMethod(
method: String,
handler: RpcHandler,
)
/**
* Unregisters a previously registered RPC method.
*
* @param method The name of the RPC method to unregister
*/
fun unregisterRpcMethod(method: String)
/**
* Initiate an RPC call to a remote participant
* @param destinationIdentity The identity of the destination participant.
* @param method The method name to call.
* @param payload The payload to pass to the method.
* @param responseTimeout Timeout for receiving a response after initial connection.
* Defaults to 10000. Max value of UInt.MAX_VALUE milliseconds.
* @return The response payload.
* @throws RpcError on failure. Details in [RpcError.message].
*/
suspend fun performRpc(
destinationIdentity: Identity,
method: String,
payload: String,
responseTimeout: Duration = 10.seconds,
): String
}
... ...