Part.1はこちら。
NodeJS製WebRTC DataChannel、NodeRTCのコードを読む Part.1 - console.lealog();
今回もSCTPの実装を読んでいく後編です。
だいぶ長丁場になってきたけど、そろそろゴールも見えてきたところ。
前編のおさらい
- SCTPのコードを追ってた
- エンドポイントの初期化を待って、SCTPのソケットを初期化してた
具体的には次のコード。
endpoint.on('association', association => { // Todo other params const socket = new Socket({ppid: this.ppid}) socket.establish(endpoint, association) this.emit('connection', socket) this.debugger.debug('connect <- %s:%s', association.remoteAddress, association.remotePort) })
この`Socket`と、`establish()`を見ていく。
class: Socket
- extends `Duplex`
- `constructor()`では特に何もしてない
- `_read()`
- 何もしてない
- `_write()`
- `this.association.SEND()`
`establish()`
- `endpoint`と`association`を引数に取る
- `association`で各イベントを購読してる
- 基本的には受けてそのまま`this.emit()`してる
- `on('DATA ARRIVE')`で`this.push()`
- 当初の使われ方にあった`socket.on('data')`へ
すごいざっくりではあるけど、これで一通りの流れは追えたはず。(メインの導線のみやけど・・)
association.on('DATA ARRIVE', streamId => { const buffer = association.RECEIVE(streamId) if (!buffer) { return } this.debugger.debug('< DATA ARRIVE %d bytes on stream %d', buffer.length, streamId) if (this.listenerCount('stream') > 0) { if (!this.streamsReadable[streamId]) { this.streamsReadable[streamId] = new SCTPStreamReadable(this, streamId) this.emit('stream', this.streamsReadable[streamId], streamId) } this.streamsReadable[streamId].push(buffer) } this.bytesRead += buffer.length this.push(buffer) })
真ん中あたりがキモで、`on('stream')`されてるなら、それ用のストリームを作って返してる。
これがSCTPのストリームで、`streamId`がそれぞれに割り振られる。
`SCTPStreamReadable`があるように`SCTPStreamWritable`もあって、それはどこかで作られるかというと、
- `createStream(streamId)`で作られる
- `SCTPStreamWritable`はソケットの参照を持つ
- `_write()`で、`this.socket.association.SEND()`
このメソッド自体は、より上層で使われるはず。
次に読むDataChannelのEstablishment Protocolのあたりで。
その他
このSCTPのモジュールに含まれてて触れてないファイルもちらっと見ておく。
chunk.js
- `endpoint`の`onPacket()`で届いたパケットをさばくための単位
- 様々な`chunkType`がある
- `init`, `init_ack`, `abort`, ...etc
- RFCにずらずら書いてあるやつ
- `fromBuffer()` / `toBuffer()`
defs.js
- いわゆる定数など
- さっきの`chunkType`ごとに決まってるパラメータなども
packet.js
- さっきの`Chunk`を内包する単位
- 個別に持ってるヘッダと`Chunk`をボディにしてまとめてる
- `fromBuffer()` / `toBuffer()`
serial.js
- 「RFC 1982 Serial Number Arithmetic」とのこと
- 一連のやり取りにおける通し番号を管理するための単位っぽい
reassembly.js
- extends `EventEmitter`
- `association`が内部的に保持する
- パケットを受け取った際に、それをどう処理するか決めるために参照される存在っぽい
- 状態を管理しておく風
- 前回見た`acceptRemote()`の先で`reassembly.init()`してる
これはがっつりRFC読まないと読めないコード・・。
読んでみて
- 今までで一番重い
- 息切れして記事がこんなに短くなるくらいに重い
- RFCを理解してないと、この程度しかわからない
- まぁこれは予想できてたことやし、理解するきっかけになればいいのでよし
- この作者これ全部1人で書いてるの・・まじ・・
とりあえずなんとなくだいたいは読めたのでもうすぐゴールできそう。