Соединение PeerJS/WebRTC не выполняется при передаче быстрых фрагментов

Я использую PeerJS, но думал, что эта проблема может быть примерно WebRTC в общем, надеюсь, что вы можете мне помочь:

Я пытаюсь написать простой обмен файлами одноранговой сети. Я использую serialisation: "none" для PeerJS соединения DataChannel, так как я отправляю только чистый ArrayBuffers.
Все хорошо с файлами около 10 Мб, но у меня проблемы с отправкой большего файла (30+ мб), например, после отправки aroung 10-20 первых фрагментов соединения с файлом в размере 900 мб между пэрами начинают метать Connection is not open. You should listen for the "open" event before sending messages. (со стороны Sender)

Моя настройка:

Файл, перетаскиваемый, чтобы перетащить & drop, Sender использует FileReader, чтобы читать его как ArrayBuffer в кусках размером 64x1024 байта (без разницы с 16x1024), и как только каждый кусок читается - он отправляется через peer.send(ChunkArrayBuffer).

Reciever создает blob из каждого полученного фрагмента, после того как завершена передача, вы получите полный blob из них и даст ссылку пользователю.

Мои настройки подключения сверстников:

   var con = peer.connect(peerid, {
        label: "file",
        reliable: true,
       serialization: "none"
   })

Моя функция отправки:

function sliceandsend(file, sendfunction) {
    var fileSize = file.size;
    var name = file.name;
    var mime = file.type;
    var chunkSize = 64 * 1024; // bytes
    var offset = 0;

 function readchunk() {
    var r = new FileReader();
    var blob = file.slice(offset, chunkSize + offset);
    r.onload = function(evt) {
        if (!evt.target.error) {
            offset += chunkSize;
            console.log("sending: " + (offset / fileSize) * 100 + "%");
            if (offset >= fileSize) {
                con.send(evt.target.result); ///final chunk
                console.log("Done reading file " + name + " " + mime);
                return;
            }
            else {                    
                con.send(evt.target.result);
            }               
        } else {
            console.log("Read error: " + evt.target.error);
            return; 
        }
        readchunk();
       };
        r.readAsArrayBuffer(blob);
    }
    readchunk();
  }

Любые идеи, что может вызвать это?

Обновление: установка 50 мс. Тайм-аут между передачами каналов помог немного, загрузка файла 900mb достигла 6% (вместо 1 - 2% ранее), прежде чем начинать бросать ошибки. Может быть, это какой-то предел одновременных операций через DataChannel или переполнение какого-то буфера DataChannel?
Update1: Здесь мой объект соединения PeerJS с объектом DataChannel внутри него:
Object visualization in Google Chrome

Ответы

Ответ 1

Хорошие новости все!
Это было переполнение буфера проблемы DataChannel, спасибо к этой статье http://viblast.com/blog/2015/2/25/webrtc-bufferedamount/

bufferedAmount является свойством объекта DataChannel (DC), который в последней версии Chrome отображает количество данных в байтах, находящихся в настоящее время в буфере, когда оно превышает 16 МБ - постоянный ток закрыт. Поэтому любой, кто столкнется с этой проблемой, должен реализовать механизм буферизации на уровне приложения, который будет следить за этим свойством и при необходимости сдерживать сообщения. Также имейте в виду, что в версиях Chrome до 37 одно и то же свойство отображает количество (не размер) сообщений, и больше того, что оно сломано под окнами и отображает 0, но с v < 37 при переполнении DC не закрыто - исключено только исключение, которое также можно поймать для указания буфера переполнение.

Я сделал редактирование в peer.js неминифицированном коде для себя, здесь вы можете увидеть оба метода в одной функции (для большей части исходного кода вы можете посмотреть https://github.com/peers/peerjs/blob/master/dist/peer.js#L217)

DataConnection.prototype._trySend = function(msg) {
var self = this;
function buffering() {
    self._buffering = true;
    setTimeout(function() {
        // Try again.
        self._buffering = false;
        self._tryBuffer();
    }, 100);
    return false;
}
if (self._dc.bufferedAmount > 15728640) {
    return buffering(); ///custom buffering if > 15MB is buffered in DC 
} else {
    try {
        this._dc.send(msg);
    } catch (e) {
        return buffering(); ///custom buffering if DC exception caught
    }
    return true;
 }        
}

Также была открыта проблема на PeerJS GitHub: https://github.com/peers/peerjs/issues/291