RPC 機能

概要

RPC 機能は DataChannel 経由で Sora の一部 HTTP API をクライアント側から呼び出しを行うための仕組みです。

RPC 機能の詳細については Sora ドキュメントの RPC 機能 をご確認ください。

前提条件

RPC を使う前提は次のとおりです。

  • Sora 接続が確立していること

    例: await Sora.createConnection(config) で作成した SoraConnection が、 conn.connect() で接続されている状態である

  • 利用したいメソッド名が、 Sora から払い出された rpc_methods に含まれていること
  • rpc DataChannel が使える状態になっていること

利用可能な RPC メソッド

利用可能なメソッド名は、 SoraSignalingMessageEvent イベント通知から取得することができます。 event.data?['type'] が offer のとき、 event.data?['rpc_methods'] にメソッド名のリストが入ります。 またメソッドは Sora の認証ウェブフックで払い出されたものだけが含まれます。

SoraSignalingMessageEvent の event プロパティが SoraSignalingEvent であり、シグナリングメッセージ本体はその data に入っています。 data は null の場合があるため、 data?['type'] のように null 安全に確認します。

以下のコード例では、接続済みの SoraConnection を conn として保持しているものとします。

import 'dart:async';

import 'package:sora_sdk/sora_sdk.dart';
void listenRpcMethods(SoraConnection conn) {
  conn.events.listen((event) {
    if (event case SoraSignalingMessageEvent(event: final signalingEvent)) {
      final data = signalingEvent.data;
      if (signalingEvent.direction == 'received' &&
          data?['type'] == 'offer') {
        final methods = data?['rpc_methods'];
        if (methods is List) {
          for (final method in methods.whereType<String>()) {
            print(method);
          }
        }
      }
    }
  });
}

RPC を送信する

RPC リクエストを送信するには rpc() を実行します。利用可能なメソッド名は、 offer の rpc_methods に含まれる文字列をそのまま使います。 SoraRpcOptions.timeout はミリ秒単位で指定します。 notification: true を指定しない通常のリクエストでは、サーバーからのレスポンスを待ちます。

Future<Object?> callRpc(SoraConnection conn) async {
  try {
    return await conn.rpc(
      // サンプルのためダミーのメソッド名です
      'example.method',
      params: <String, Object?>{'value': 123},
      options: const SoraRpcOptions(timeout: 5000),
    );
  } on SoraRpcError catch (error) {
    print('${error.code} ${error.message}');
  } on TimeoutException {
    print('timeout');
  }
  return null;
}

Notification として送信する

レスポンス不要で送る場合は notification: true を使います。

Future<void> sendNotification(SoraConnection conn) async {
  await conn.rpc(
    'example.notify',
    params: <String, Object?>{'message': 'hello'},
    options: const SoraRpcOptions(notification: true),
  );
}

RequestSimulcastRid メソッドのリクエスト例

サイマルキャストにおいて受信側で希望する RID を変更したい場合の例です。

Future<Object?> requestSimulcastRid(SoraConnection conn) {
  return conn.rpc(
    'RequestSimulcastRid',
    params: <String, Object?>{
      'channel_id': 'example-channel',
      'receiver_connection_id': conn.connectionId,
      'sender_connection_id': '',
      'rid': 'r1',
    },
  );
}

PutSignalingNotifyMetadataItem メソッドのリクエスト例

シグナリング通知メタデータの 1 項目を更新したい場合の例です。

Future<Object?> putSignalingNotifyMetadataItem(SoraConnection conn) {
  return conn.rpc(
    'PutSignalingNotifyMetadataItem',
    params: <String, Object?>{
      'channel_id': 'example-channel',
      'connection_id': conn.connectionId,
      'key': 'display_name',
      'value': 'Alice',
    },
  );
}

エラーハンドリング

  • サーバーから RPC エラーが返ると SoraRpcError
  • タイムアウトを超えると TimeoutException
  • 切断時は待機中の RPC が SoraRpcError(code: -1, message: 'Disconnected') で完了
  • SoraConnection.dispose() 後に rpc() を呼ぶと StateError

SoraConnectionErrorEvent は接続自体のエラーを通知するイベントです。 RPC サーバーが返したエラーは SoraRpcError 、RPC の応答待ちが指定時間を超えた場合は TimeoutException で処理します。

Future<void> callRpcWithErrorHandling(SoraConnection conn) async {
  try {
    await conn.rpc(
      'example.method',
      options: const SoraRpcOptions(timeout: 3000),
    );
  } on SoraRpcError catch (error) {
    print(error);
  } on TimeoutException {
    print('timeout');
  }
}