Home Reference Source

js/Channel.js

import Mitt from './util/Mitt.js'

/**
 * 양방향 데이터 전송을 위한 인터페이스. RTCSocket을 이용해 데이터를 전송합니다.
 */
export default class Channel extends Mitt {
  /**
   * 주의: 이 생성자는 RTCEngine 내부에서만 호출되어야 합니다.
   * @param {RTCSocket} socket 데이터 전송에 사용할 RTCSocket
   * @param {RTCEngine} engine 이 채널을 생성한 엔진
   */
  constructor (socket, engine) {
    super()

    this.engine = engine
    this.socket = socket
    this.socket.on('data', data => this.emit('message', data))
    this.label = this.socket.dataChannel.label
    this.filesSent = 0

    this.socket.on('__file-transaction', label => this.receiveTransaction(label))
  }

  /**
   * 상대가 파일을 보내기 위해 트렌젝션을 만들었을때 파일을 받기 위한 트렌젝션을 생성하고 `transaction` 이벤트로 알립니다.
   * @deprecated
   * @param {string} label 트렌젝션의 식별자
   */
  async receiveTransaction (label) {
    const transaction = await this.engine.readable(label)
    this.emit('transaction', transaction)
  }

  /**
   * 채널을 통해서 데이터를 전송합니다. `File` 데이터를 받으면 새로운 트렌젝션을 만들고 그걸 통해 파일의 데이터를 전송합니다.
   * 받는쪽에서는 `transaction` 이벤트를 통해 파일을 받을 수 있습니다.
   * @deprecated
   * @param {*} data 전송할 데이터. `JSON.stringify()`로 JSON 문자열로 바꿀 수 있거나 `ArrayBuffer`의 타입은 그냥 전송하고, `File`인 경우 새로운 트렌젝션을 만듭니다.
   * @returns {Promise<Transaction|void>} 파일 전송을 위한 트렌젝션 또는 데이터가 성공적으로 전송되면 resolve하는 promise
   */
  async send (data) {
    if (data instanceof File) {
      const file = data
      const label = `file - ${this.filesSent++}`
      this.socket.writeEvent('__file-transaction', label)

      const transaction = await this.engine.writable(label, {
        name: file.name,
        size: file.size
      })

      file.stream().pipeTo(transaction.stream)
      return transaction
    }

    return this.socket.write(data)
  }
}