Commit 60ba4aa7 authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Fix file transfer for Firefox.

Firefox implements the spec correctly by encapsulatings received
data in a blob by default.  Handle both blobs and ArrayBuffers.

Also improve error handling.
parent 6d250bfa
...@@ -2163,7 +2163,7 @@ async function gotJoined(kind, group, perms, status, data, message) { ...@@ -2163,7 +2163,7 @@ async function gotJoined(kind, group, perms, status, data, message) {
* @property {number} size * @property {number} size
* @property {string} type * @property {string} type
* @property {Array<RTCIceCandidateInit>} [candidates] * @property {Array<RTCIceCandidateInit>} [candidates]
* @property {Array<Uint8Array>} [data] * @property {Array<Blob|ArrayBuffer>} [data]
* @property {number} [datalen] * @property {number} [datalen]
* @property {boolean} [done] * @property {boolean} [done]
*/ */
...@@ -2302,6 +2302,18 @@ function setFileStatus(up, id, fileid, status, delyes, delno) { ...@@ -2302,6 +2302,18 @@ function setFileStatus(up, id, fileid, status, delyes, delno) {
} }
} }
/**
* @param {boolean} up
* @param {string} id
* @param {string} fileid
* @param {any} message
*/
function failFile(up, id, fileid, message) {
console.error('File transfer failed:', message);
setFileStatus(up, id, fileid, message ? `Failed: ${message}` : 'Failed.');
deleteTransferredFile(true, id, fileid);
}
/** /**
* @param {string} username * @param {string} username
* @param {string} id * @param {string} id
...@@ -2374,11 +2386,24 @@ async function getFile(id, fileid) { ...@@ -2374,11 +2386,24 @@ async function getFile(id, fileid) {
f.data = []; f.data = [];
f.datalen = 0; f.datalen = 0;
dc.onclose = function(e) { dc.onclose = function(e) {
try {
closeReceiveFileData(id, fileid, f); closeReceiveFileData(id, fileid, f);
} catch(e) {
failFile(false, id, fileid, e);
} }
};
dc.onmessage = function(e) { dc.onmessage = function(e) {
try {
receiveFileData(id, fileid, f, dc, e.data); receiveFileData(id, fileid, f, dc, e.data);
} catch(e) {
failFile(false, id, fileid, e);
} }
};
dc.onerror = function(e) {
/** @ts-ignore */
let err = e.error;
failFile(false, id, fileid, err);
};
let offer = await pc.createOffer(); let offer = await pc.createOffer();
if(!offer) if(!offer)
throw new Error("Couldn't create offer"); throw new Error("Couldn't create offer");
...@@ -2433,17 +2458,28 @@ async function sendFile(id, fileid, sdp) { ...@@ -2433,17 +2458,28 @@ async function sendFile(id, fileid, sdp) {
}; };
let file = f.file; let file = f.file;
pc.ondatachannel = function(e) { pc.ondatachannel = function(e) {
e.channel.onopen = function(e) { let dc = /** @type{RTCDataChannel} */(e.channel);
let dc = /** @type{RTCDataChannel} */(e.target);
dc.onmessage = function(e) {
ackSendFileData(id, fileid, f, e.data);
}
dc.onclose = function(e) { dc.onclose = function(e) {
try {
closeSendFileData(id, fileid, f); closeSendFileData(id, fileid, f);
} catch(e) {
failFile(true, id, fileid, e);
} }
sendFileData(id, fileid, f, dc, file); };
dc.onerror = function(e) {
/** @ts-ignore */
let err = e.error;
failFile(true, id, fileid, err);
}
dc.onmessage = function(e) {
try {
ackSendFileData(id, fileid, f, e.data);
} catch(e) {
failFile(true, id, fileid, e);
} }
}; };
sendFileData(id, fileid, f, dc, file);
};
await pc.setRemoteDescription({ await pc.setRemoteDescription({
type: 'offer', type: 'offer',
...@@ -2552,11 +2588,19 @@ function closeSendFileData(id, fileid, f) { ...@@ -2552,11 +2588,19 @@ function closeSendFileData(id, fileid, f) {
* @param {string} fileid * @param {string} fileid
* @param {transferredFile} f * @param {transferredFile} f
* @param {RTCDataChannel} dc * @param {RTCDataChannel} dc
* @param {Uint8Array} data * @param {Blob|ArrayBuffer} data
*/ */
function receiveFileData(id, fileid, f, dc, data) { function receiveFileData(id, fileid, f, dc, data) {
f.data.push(data); f.data.push(data);
if(data instanceof Blob) {
f.datalen += data.size;
} else if(data instanceof ArrayBuffer) {
f.datalen += data.byteLength; f.datalen += data.byteLength;
} else {
console.error('Unexpeced type for received data', data);
throw new Error('unexpected type for received data');
}
setFileStatus( setFileStatus(
false, id, fileid, `Downloading... ${f.datalen}/${f.size}`, true, false, id, fileid, `Downloading... ${f.datalen}/${f.size}`, true,
); );
...@@ -2570,6 +2614,9 @@ function receiveFileData(id, fileid, f, dc, data) { ...@@ -2570,6 +2614,9 @@ function receiveFileData(id, fileid, f, dc, data) {
return; return;
} }
dc.onmessage = null;
dc.onerror = null;
dc.send('done'); dc.send('done');
setFileStatus(false, id, fileid, 'Done.', true, true); setFileStatus(false, id, fileid, 'Done.', true, true);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment