import debug from "debug" ; import { Event } from "rx.mini" ; import { EventTarget } from "./helper" ; import { RTCSctpTransport } from "./transport/sctp" ; import { Callback , CallbackWithValue } from "./types/util" ; const log = debug ( "werift/webrtc/datachannel" ) ; export class RTCDataChannel extends EventTarget { readonly stateChanged = new Event < [ DCState ] > ( ) ; readonly message = new Event < [ string | Buffer ] > ( ) ; readonly error = new Event < [ Error ] > ( ) ; readonly bufferedAmountLow = new Event ( ) ; onopen ? : Callback ; onclose ? : Callback ; onclosing ? : Callback ; onmessage ? : CallbackWithValue < MessageEvent > ; onerror ? : CallbackWithValue < RTCErrorEvent > ; isCreatedByRemote = false ; id : number = this . parameters . id ; readyState : DCState = "connecting" ; bufferedAmount = 0 ; private _bufferedAmountLowThreshold = 0 ; constructor ( private readonly transport , private readonly parameters , public readonly sendOpen = true ) { super ( ) ; if ( parameters . negotiated ) { if ( this . id == undefined || this . id < 0 || this . id > 65534 ) { throw new Error ( "ID must be in range 0-65534 if data channel is negotiated out-of-band" ) ; } this . transport . dataChannelAddNegotiated ( this ) ; } else { if ( sendOpen ) { this . sendOpen = false ; this . transport . dataChannelOpen ( this ) ; } } } get ordered ( ) { return this . parameters . ordered ; } get maxRetransmits ( ) { return this . parameters . maxRetransmits ; } get maxPacketLifeTime ( ) { return this . parameters . maxPacketLifeTime ; } get label ( ) { return this . parameters . label ; } get protocol ( ) { return this . parameters . protocol ; } get negotiated ( ) { return this . parameters . negotiated ; } get bufferedAmountLowThreshold ( ) { return this . _bufferedAmountLowThreshold ; } set bufferedAmountLowThreshold ( value ) { if ( value < 0 || value > 4294967295 ) throw new Error ( "bufferedAmountLowThreshold must be in range 0 - 4294967295" ) ; this . bufferedAmountLowThreshold = value ; } setId ( id ) { this . id = id ; } setReadyState ( state ) { if ( state !== this . readyState ) { this . readyState = state ; this . stateChanged . execute ( state ) ; switch ( state ) { case "open" : if ( this . onopen ) this . onopen ( ) ; this . emit ( "open" ) ; break ; case "closed" : if ( this . onclose ) this . onclose ( ) ; this . emit ( "close" ) ; break ; case "closing" : if ( this . onclosing ) this . onclosing ( ) ; break ; } log ( "change state" , state ) ; } } addBufferedAmount ( amount ) { const crossesThreshold = this . bufferedAmount > this . bufferedAmountLowThreshold && this . bufferedAmount + amount <= this . bufferedAmountLowThreshold ; this . bufferedAmount += amount ; if ( crossesThreshold ) { this . bufferedAmountLow . execute ( ) ; this . emit ( "bufferedamountlow" ) ; } } send ( data ) { this . transport . datachannelSend ( this , data ) ; } close ( ) { this . transport . dataChannelClose ( this ) ; } } export type DCState = "open" | "closed" | "connecting" | "closing" ; export class RTCDataChannelParameters { label = "" ; maxPacketLifeTime ? : number ; maxRetransmits ? : number ; ordered = true ; protocol = "" ; negotiated = false ; id ! : number ; constructor ( props = { } ) { Object . assign ( this , props ) ; } } export interface MessageEvent { data : string | Buffer ; } export interface RTCErrorEvent { error : any ; }