# メッセージング機能

> **注意**
>
> メッセージング機能は実験的機能のため、正式版では仕様が変更される可能性があります

## 概要

ここでは DataChannel を利用したメッセージング機能について説明します。

DataChannel は、WebRTC の機能の一つでデータの送受信を行える機能です。

## 注意

- メッセージング機能を利用するためには、 `data_channel_siganling` が有効になっている必要があります
- メッセージング機能は DataChannel プロトコル互換性を維持しつつ Sora 独自の仕組みを追加しています

## 制限

### メッセージサイズ制限

> **注意**
>
> 1 回のメッセージで送れる値には制限がありますのでご注意ください。

詳しくは DataChannel シグナリングの [推奨メッセージサイズ](DATA_CHANNEL_SIGNALING.html#2b27d3) をご確認ください

## SDK 対応状況

- 最新版の JavaScript SDK- 対応済みです
- 最新版の iOS SDK- 対応済みです
- 最新版の Android SDK- 対応済みです
- 最新版の Unity SDK- 対応済みです
- 最新版の C++ SDK- 対応済みです

## DataChannel を利用したメッセージング機能を有効にする

DataChannel を利用したメッセージングを利用する場合、 DataChannel シグナリングが有効になっている必要があります。

その上で `sora.conf` にて [data_channel_messaging](SORA_CONF.html#1d5746) を `true` に指定してください。

利用する場合は `{"type": "connect"}` 時に `data_channels` を指定してください。

## メッセージング用 DataChannel の作成

> **重要**
>
> DataChannel を利用したメッセージングを利用する場合は、DataChannel シグナリングが有効になっている必要があります

Sora では、Sora がシグナリングで使用する DataChannel 以外にも、メッセージング用の DataChannel を作成できます。

利用する場合は `{"type": "connect"}` 時に定義するか、認証成功時の払い出しで定義する必要があります。

Sora のメッセージング用 DataChannel は、DataChannel の属性である `label` を定義する際に必ず `#` から始める必要があります。


## data_channels 仕様

> **警告**
>
> 現時点では誰から送られたメッセージかを判断する仕組みはありません。

> **重要**
>
> メッセージは **送信者以外** の同一 `label` 、かつ、 `direction` が `sendrecv`
> または `recvonly` のクライアントに送信されます。


### label

メッセージのラベルを指定します。先頭に `#` が付いている必要があります。

- `label` は `#` を含めて 32 文字まで指定可能です
- `label` には小文字大文字のアルファベットと `-` (ハイフン) しか利用できません- `#` の次の文字に `-` は指定できません
  - `^#[a-zA-Z0-9][a-zA-Z0-9-]{1,30}$`
- 1 接続においてラベルは最大で 1024 まで指定可能です


### compress

メッセージを zlib にて圧縮するかどうかを指定します。

- `compress` が `true` の場合、圧縮/展開に `zlib.deflate` を利用します- 圧縮方式を変更することはできません


### direction

メッセージの方向を指定します。

- `direction` には `sendrecv` / `sendonly` / `recvonly` が設定できます- `sendrecv` 時に **自分が送ったメッセージ** は自分には送られてきません

クライアントからみた方向になります。

- `sendrecv` が設定されたラベルは送受信可能です
- `sendonly` が設定されたラベルは送信のみ可能です
- `recvonly` が設定されたラベルは受信のみ可能です


### ordered

順序保証を行うかどうか指定します。デフォルトでは `true` に設定され、順序保証を行います。


### max_retransmits

> **注意**
>
> max_retransmits と max_packet_life_time はどちらかしか指定できません。

最大再送回数を指定します。デフォルトでは未指定で、無制限に再送します。


### max_packet_life_time

> **注意**
>
> max_retransmits と max_packet_life_time はどちらかしか指定できません。

最大再送時間を指定します。デフォルトでは未指定で、無制限に再送します。

### JavaScript SDK 利用時の注意

- `max_retransmits` は `maxRetransmits` に変更してください
- `max_packet_life_time` は `maxPacketLifeTime` に変更してください

## "type": "connect" 時の "data_channels"

> **注釈**
>
> protocol は特に指定する必要はありません。

* - 項目名
  - 型
  - 必須 / オプション
  - デフォルト
  - 備考
* - label
  - string
  - 必須
  -
  - ^#[a-zA-Z0-9][a-zA-Z0-9-]{1,30}$
* - direction
  - string
  - 必須
  -
  - "sendrecv" / "sendonly" / "recvonly"
* - ordered
  - boolean
  - オプション
  - true
  -
* - max_packet_life_time
  - integer
  - オプション
  - 未指定
  -
* - max_retransmits
  - integer
  - オプション
  - 未指定
  -
* - protocol
  - string
  - オプション
  - ""
  -
* - compress
  - boolean
  - オプション
  - false
  -

> **注意**
>
> Sora JS SDK や Sora DevTools で `max_packet_life_time` と `max_retransmits` を指定する場合は
> `maxPacketLifeTime` と `maxRetransmits` となります。

```javascript
{
    "type": "connect",
    "data_channels": [
        {
            "label": "#spam",
            "max_packet_life_time": 5000,
            "ordered": true,
            "protocol": "efg",
            "compress": false,
            "direction": "sendonly"
        },
        {
            "label": "#egg",
            "max_retransmits": 0,
            "ordered": false,
            "protocol": "abc",
            "compress": false,
            "direction": "recvonly"
        }
    ]
}
```

## 認証成功時の戻り値

認証ウェブフックの認証成功時に `data_channels` を指定することができます。

```javascript
{
    "allowed": true,
    "data_channels": [
        {
            "label": "#spam",
            "max_packet_life_time": 5000,
            "ordered": true,
            "protocol": "efg",
            "compress": false,
            "direction": "sendonly"
        },
        {
            "label": "#egg",
            "max_retransmits": 0,
            "ordered": false,
            "protocol": "abc",
            "compress": false,
            "direction": "recvonly"
        }
    ]
}
```

## "type": "offer" 時の "data_channels"

> **注釈**
>
> Sora SDK を利用する場合はこれを意識する必要はありません。

接続時か認証成功時に指定された `data_channels` は `{"type": "offer"}` に含まれます。

```javascript
{
    "type": "offer",
    "data_channels": [
        {
            "label": "signaling",
            "ordered": true,
            "protocol": "signaling",
            "compress": true,
            "direction": "sendrecv"
        },
        {
            "label": "notify",
            "ordered": true,
            "protocol": "notify",
            "compress": true,
            "direction": "recvonly"
        },
        {
            "label": "push",
            "ordered": true,
            "protocol": "push",
            "compress": true,
            "direction": "recvonly"
        },
        {
            "label": "stats",
            "ordered": true,
            "max_retransmits": 1,
            "protocol": "stats",
            "compress": true,
            "direction": "sendrecv"
        },
        {
            "label": "#spam",
            "max_packet_life_time": 5000,
            "ordered": true,
            "protocol": "efg",
            "compress": false,
            "direction": "sendrecv"
        },
        {
            "label": "#egg",
            "max_retransmits": 0,
            "ordered": false,
            "protocol": "abc",
            "compress": false
            "direction": "recvonly"
        }
    ]
}
```

## DataChannel を利用したメッセージングのみで接続する

DataChannel を利用したメッセージングのみを有効にするには以下を満たす必要があります。

- `sora.conf` の `default_data_channel_signaling` を `true` にする
- `sora.conf` の `data_channel_messaging_only` を `true` にする
- `sora.conf` の `data_channel_messaging` を `true` にする
- `{"type": "connect"}` 時に `role` を `sendrecv` にする
- `{"type": "connect"}` 時に `multistream` を `true` にする
- `{"type": "connect"}` 時に `audio` を `false` にする- 認証成功時の払い出しでも可
- `{"type": "connect"}` 時に `video` を `false` にする- 認証成功時の払い出しでも可
- `{"type": "connect"}` 時に `data_channels` を指定する- 認証成功時の払い出しでも可
- `{"type": "connect"}` 時に `data_channel_signaling` を `true` にする- 認証成功時の払い出しでも可

これで音声や映像を送らず、 DataChannel を利用したメッセージングのみを利用することが可能になります。

## シーケンス図

### シンプル

1. クライアント 1 が `label`: `spam`, `direction`: `sendrecv` と、`label`: `#egg`, `direction`: `sendonly` でメッセージング利用開始```javascript
   {"type": "connect",
    "data_channels": [{"label": "#spam", "direction": "sendrecv"},
                      {"label": "#egg": "direction": "sendonly"}]}
   ```
2. クライアント 2 が `label`: `#spam`, `direction`: `recvonly` でメッセージング利用開始```javascript
   {"type": "connect",
    "data_channels": [{"label": "#spam", "direction": "recvonly"}]}
   ```
3. クライアント 1 が `label`: `#spam` へメッセージ `"abc"` を送信
4. クライアント 2 が Sora から `label`: `#spam` へのメッセージ `"abc"` を受信
5. クライアント 1 が `label`: `#egg` へメッセージ `"xyz"` を送信- 誰も受け取る人がいない
6. クライアント 3 が `label`: `#spam`, `direction`: `sendrecv` でメッセージング利用開始```javascript
   {"type": "connect",
    "data_channels": [{"label": "#spam", "direction": "sendrecv"}]}
   ```
7. クライアント 1 が Sora へ `label`: `#spam` のメッセージ `"123"` を送信
8. クライアント 2 が Sora から `label`: `#spam` のメッセージ `"123"` を受信
9. クライアント 3 が Sora から `label`: `#spam` のメッセージ `"123"` を受信

seqdiag {
    default_fontsize = 18;
    edge_length = 200;
    activation = none;

    クライアント1; クライアント2; クライアント3; Sora;

    クライアント1 ->> Sora [label = '1. type: connect'];

    === クライアント1 WebRTC 確立 ===

    クライアント2 ->> Sora [label = '2. type: connect'];

    === クライアント2 WebRTC 確立 ===


    クライアント1 ->> Sora [label = '3. label: #spam'];
    クライアント2 <<- Sora [label = '4. label: #spam'];
    クライアント1 ->> Sora [label = '5. label: #egg'];

    クライアント3 ->> Sora [label = '6. type: connect'];

    === クライアント3 WebRTC 確立 ===

    クライアント1 ->> Sora [label = '7. label: #spam'];
    クライアント3 <<- Sora [label = '8. label: #spam'];
    クライアント2 <<- Sora [label = '9. label: #spam'];

}
