Explorar o código

Implement chunking for relayed data task messages

Danilo Bargen %!s(int64=7) %!d(string=hai) anos
pai
achega
b783497055
Modificáronse 3 ficheiros con 46 adicións e 17 borrados
  1. 1 0
      karma.conf.js
  2. 43 17
      src/services/webclient.ts
  3. 2 0
      tests/testsuite.html

+ 1 - 0
karma.conf.js

@@ -9,6 +9,7 @@ module.exports = function(config) {
             'node_modules/angular-aria/angular-aria.min.js',
             'node_modules/angular-animate/angular-animate.min.js',
             'node_modules/angular-material/angular-material.min.js',
+            'node_modules/@saltyrtc/chunked-dc/dist/chunked-dc.es5.js',
             'dist/app.js',
             'dist/ts-tests.js',
             'tests/filters.js',

+ 43 - 17
src/services/webclient.ts

@@ -15,6 +15,7 @@
  * along with Threema Web. If not, see <http://www.gnu.org/licenses/>.
  */
 
+/// <reference types="@saltyrtc/chunked-dc" />
 /// <reference types="@saltyrtc/task-webrtc" />
 /// <reference types="@saltyrtc/task-relayed-data" />
 
@@ -154,6 +155,11 @@ export class WebClientService {
     private secureDataChannel: saltyrtc.tasks.webrtc.SecureDataChannel = null;
     public chosenTask: threema.ChosenTask = threema.ChosenTask.None;
 
+    // Message chunking
+    private messageSerial = 0;
+    private messageChunkSize = 64 * 1024;
+    private unchunker: chunkedDc.Unchunker = null;
+
     // Messenger data
     public messages: threema.Container.Messages;
     public conversations: threema.Container.Conversations;
@@ -572,7 +578,9 @@ export class WebClientService {
         } else if (this.chosenTask === threema.ChosenTask.RelayedData) {
             // Handle messages directly
             this.relayedDataTask.on('data', (ev: saltyrtc.SaltyRTCEvent) => {
-                this.handleIncomingMessage(ev.data, true);
+                const chunk = new Uint8Array(ev.data);
+                this.$log.debug('[Chunk] Received chunk:', chunk);
+                this.unchunker.add(chunk.buffer);
             });
 
             // The communication channel is now open! Fetch initial data
@@ -1053,9 +1061,11 @@ export class WebClientService {
 
                         break;
                     case 'file':
-                        // validate max file size
-                        if ((message as threema.FileMessageData).size > WebClientService.MAX_FILE_SIZE) {
-                            return reject(this.$translate.instant('error.FILE_TOO_LARGE'));
+                        // Validate max file size
+                        if (this.chosenTask === threema.ChosenTask.WebRTC) {
+                            if ((message as threema.FileMessageData).size > WebClientService.MAX_FILE_SIZE) {
+                                return reject(this.$translate.instant('error.FILE_TOO_LARGE'));
+                            }
                         }
 
                         // Determine required feature mask
@@ -1532,6 +1542,10 @@ export class WebClientService {
         // Reset initialization data
         this._resetInitializationSteps();
 
+        // Initialize unchunker
+        this.unchunker = new chunkedDc.Unchunker();
+        this.unchunker.onMessage = this.handleIncomingMessageBytes.bind(this);
+
         // Create container instances
         this.receivers = this.container.createReceivers();
         this.conversations = this.container.createConversations();
@@ -2775,23 +2789,35 @@ export class WebClientService {
         }
         switch (this.chosenTask) {
             case threema.ChosenTask.WebRTC:
-                // Send bytes through WebRTC DataChannel
-                const bytes: Uint8Array = this.msgpackEncode(message);
-                this.secureDataChannel.send(bytes);
+                {
+                    // Send bytes through WebRTC DataChannel
+                    const bytes: Uint8Array = this.msgpackEncode(message);
+                    this.secureDataChannel.send(bytes);
+                }
                 break;
             case threema.ChosenTask.RelayedData:
-                // Send bytes through e2e encrypted WebSocket
-                if (this.salty.state !== 'task') {
-                    this.$log.debug(this.logTag, 'Currently not connected (state='
-                        + this.salty.state + '), putting outgoing message in queue');
-                    this.outgoingMessageQueue.push(message);
-                    if (this.pushService.isAvailable()) {
-                        this.sendPush(threema.WakeupType.Wakeup);
+                {
+                    // Send bytes through e2e encrypted WebSocket
+                    if (this.salty.state !== 'task') {
+                        this.$log.debug(this.logTag, 'Currently not connected (state='
+                            + this.salty.state + '), putting outgoing message in queue');
+                        this.outgoingMessageQueue.push(message);
+                        if (this.pushService.isAvailable()) {
+                            this.sendPush(threema.WakeupType.Wakeup);
+                        } else {
+                            this.$log.warn(this.logTag, 'Push service not available, cannot wake up peer!');
+                        }
                     } else {
-                        this.$log.warn(this.logTag, 'Push service not available, cannot wake up peer!');
+                        const bytes: Uint8Array = this.msgpackEncode(message);
+                        const chunker = new chunkedDc.Chunker(this.messageSerial, bytes, this.messageChunkSize);
+                        for (const chunk of chunker) {
+                            if (this.config.MSG_DEBUGGING) {
+                                this.$log.debug('[Chunk] Sending chunk:', chunk);
+                            }
+                            this.relayedDataTask.sendMessage(chunk.buffer);
+                        }
+                        this.messageSerial += 1;
                     }
-                } else {
-                    this.relayedDataTask.sendMessage(message);
                 }
                 break;
         }

+ 2 - 0
tests/testsuite.html

@@ -18,6 +18,8 @@
         <script src="../node_modules/angular-animate/angular-animate.min.js"></script>
         <script src="../node_modules/angular-aria/angular-aria.min.js"></script>
 
+        <script src="../node_modules/@saltyrtc/chunked-dc/dist/chunked-dc.es5.js"></script>
+
         <script src="../dist/app.js"></script>
         <script src="../dist/ts-tests.js"></script>