diff --git a/flottform/forms/src/flottform-channel-client.ts b/flottform/forms/src/flottform-channel-client.ts index ed66a1f..cd68b95 100644 --- a/flottform/forms/src/flottform-channel-client.ts +++ b/flottform/forms/src/flottform-channel-client.ts @@ -15,6 +15,8 @@ type Listeners = { 'connecting-to-host': []; connected: []; 'connection-impossible': []; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + 'receiving-data': [e: any]; done: []; disconnected: []; error: [e: string]; @@ -53,6 +55,9 @@ export class FlottformChannelClient extends EventEmitter { this.rtcConfiguration = rtcConfiguration; this.pollTimeForIceInMs = pollTimeForIceInMs; this.logger = logger; + Promise.resolve().then(() => { + this.changeState('init'); + }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -97,15 +102,8 @@ export class FlottformChannelClient extends EventEmitter { this.logger.info(`ondatachannel: ${e.channel}`); this.changeState('connected'); this.dataChannel = e.channel; - // Set the maximum amount of data waiting inside the datachannel's buffer - this.dataChannel.bufferedAmountLowThreshold = this.BUFFER_THRESHOLD; - // Set the listener to listen then emit an event when the buffer has more space available and can be used to send more data - this.dataChannel.onbufferedamountlow = () => { - this.emit('bufferedamountlow'); - }; - this.dataChannel.onopen = (e) => { - this.logger.info(`ondatachannel - onopen: ${e.type}`); - }; + this.configureDataChannel(); + this.setupDataChannelListener(); }; this.changeState('sending-client-info'); @@ -123,11 +121,41 @@ export class FlottformChannelClient extends EventEmitter { this.changeState('disconnected'); }; - // sendData = (data: string | Blob | ArrayBuffer | ArrayBufferView) => { + private setupDataChannelListener = () => { + if (!this.dataChannel) { + this.changeState( + 'error', + 'dataChannel is not defined. Unable to setup the listeners for the data channel' + ); + return; + } + + this.dataChannel.onmessage = (e) => { + // Handling the incoming data from the Host depends on the use case. + this.emit('receiving-data', e); + }; + }; + + private configureDataChannel = () => { + if (!this.dataChannel) { + this.changeState('error', 'dataChannel is not defined! Unable to configure it!'); + return; + } + // Set the maximum amount of data waiting inside the datachannel's buffer + this.dataChannel.bufferedAmountLowThreshold = this.BUFFER_THRESHOLD; + // Set the listener to listen then emit an event when the buffer has more space available and can be used to send more data + this.dataChannel.onbufferedamountlow = () => { + this.emit('bufferedamountlow'); + }; + this.dataChannel.onopen = (e) => { + this.logger.info(`ondatachannel - onopen: ${e.type}`); + }; + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any sendData = (data: any) => { - if (this.dataChannel == null) { - this.changeState('error', 'dataChannel is null. Unable to send the file to the Host!'); + if (!this.dataChannel) { + this.changeState('error', 'dataChannel is not defined. Unable to send the file to the Host!'); return; } else if (!this.canSendMoreData()) { this.logger.warn('Data channel is full! Cannot send data at the moment'); diff --git a/flottform/forms/src/flottform-channel-host.ts b/flottform/forms/src/flottform-channel-host.ts index 8ade217..abcf68a 100644 --- a/flottform/forms/src/flottform-channel-host.ts +++ b/flottform/forms/src/flottform-channel-host.ts @@ -20,6 +20,7 @@ export class FlottformChannelHost extends EventEmitter { private openPeerConnection: RTCPeerConnection | null = null; private dataChannel: RTCDataChannel | null = null; private pollForIceTimer: NodeJS.Timeout | number | null = null; + private BUFFER_THRESHOLD = 128 * 1024; // 128KB buffer threshold (maximum of 4 chunks in the buffer waiting to be sent over the network) constructor({ flottformApi, @@ -71,6 +72,10 @@ export class FlottformChannelHost extends EventEmitter { this.openPeerConnection = new RTCPeerConnection(this.rtcConfiguration); this.dataChannel = this.createDataChannel(); + if (this.dataChannel) { + this.configureDataChannel(); + this.setupDataChannelListener(); + } const session = await this.openPeerConnection.createOffer(); await this.openPeerConnection.setLocalDescription(session); @@ -121,6 +126,40 @@ export class FlottformChannelHost extends EventEmitter { }; }; + private configureDataChannel = () => { + if (this.dataChannel == null) { + this.changeState('error', 'dataChannel is null. Unable to setup the configure it!'); + return; + } + // Set the maximum amount of data waiting inside the datachannel's buffer + this.dataChannel.bufferedAmountLowThreshold = this.BUFFER_THRESHOLD; + // Set the listener to listen then emit an event when the buffer has more space available and can be used to send more data + this.dataChannel.onbufferedamountlow = () => { + this.emit('bufferedamountlow'); + }; + this.dataChannel.onopen = (e) => { + this.logger.info(`ondatachannel - onopen: ${e.type}`); + }; + }; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + sendData = (data: any) => { + if (this.dataChannel == null) { + this.changeState('error', 'dataChannel is null. Unable to send the data to the Client!'); + return; + } else if (!this.canSendMoreData()) { + this.logger.warn('Data channel is full! Cannot send data at the moment'); + return; + } + this.dataChannel.send(data); + }; + + canSendMoreData = () => { + return ( + this.dataChannel && + this.dataChannel.bufferedAmount < this.dataChannel.bufferedAmountLowThreshold + ); + }; + private setupHostIceGathering = ( putHostInfoUrl: string, hostKey: string, @@ -280,7 +319,7 @@ export class FlottformChannelHost extends EventEmitter { this.dataChannel.onerror = (e) => { this.logger.log('channel.onerror', e); - this.changeState('error', { message: 'file-transfer' }); + this.changeState('error', { message: e.error.message }); }; }; diff --git a/flottform/forms/src/internal.ts b/flottform/forms/src/internal.ts index 2658b9c..4c51cff 100644 --- a/flottform/forms/src/internal.ts +++ b/flottform/forms/src/internal.ts @@ -122,6 +122,7 @@ export type FlottformEventMap = { error: [error: Error]; connected: []; disconnected: []; + bufferedamountlow: []; }; // eslint-disable-next-line @typescript-eslint/no-explicit-any