Blame view

static/plugins/spice-html5/wire.js 3.92 KB
831eac332   zhuzhenchao   add file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
  "use strict";
  /*
     Copyright (C) 2012 by Jeremy P. White <jwhite@codeweavers.com>
  
     This file is part of spice-html5.
  
     spice-html5 is free software: you can redistribute it and/or modify
     it under the terms of the GNU Lesser General Public License as published by
     the Free Software Foundation, either version 3 of the License, or
     (at your option) any later version.
  
     spice-html5 is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU Lesser General Public License for more details.
  
     You should have received a copy of the GNU Lesser General Public License
     along with spice-html5.  If not, see <http://www.gnu.org/licenses/>.
  */
  
  /*--------------------------------------------------------------------------------------
  **  SpiceWireReader
  **      This class will receive messages from a WebSocket and relay it to a given
  **  callback.  It will optionally save and pass along a header, useful in processing
  **  the mini message format.
  **--------------------------------------------------------------------------------------*/
  function SpiceWireReader(sc, callback)
  {
      this.sc = sc;
      this.callback = callback;
      this.needed = 0;
  
      this.buffers = [];
  
      this.sc.ws.wire_reader = this;
      this.sc.ws.binaryType = "arraybuffer";
      this.sc.ws.addEventListener('message', wire_blob_catcher);
  }
  
  SpiceWireReader.prototype =
  {
  
      /*------------------------------------------------------------------------
      **  Process messages coming in from our WebSocket
      **----------------------------------------------------------------------*/
      inbound: function (mb)
      {
          var at;
  
          /* Just buffer if we don't need anything yet */
          if (this.needed == 0)
          {
              this.buffers.push(mb);
              return;
          }
  
          /* Optimization - if we have just one inbound block, and it's
              suitable for our needs, just use it.  */
          if (this.buffers.length == 0 && mb.byteLength >= this.needed)
          {
              if (mb.byteLength > this.needed)
              {
                  this.buffers.push(mb.slice(this.needed));
                  mb = mb.slice(0, this.needed);
              }
              this.callback.call(this.sc, mb,
                          this.saved_msg_header || undefined);
          }
          else
          {
              this.buffers.push(mb);
          }
  
  
          /* If we have fragments that add up to what we need, combine them */
          /*  FIXME - it would be faster to revise the processing code to handle
          **          multiple fragments directly.  Essentially, we should be
          **          able to do this without any slice() or combine_array_buffers() calls */
          while (this.buffers.length > 1 && this.buffers[0].byteLength < this.needed)
          {
              var mb1 = this.buffers.shift();
              var mb2 = this.buffers.shift();
  
              this.buffers.unshift(combine_array_buffers(mb1, mb2));
          }
  
  
          while (this.buffers.length > 0 && this.buffers[0].byteLength >= this.needed)
          {
              mb = this.buffers.shift();
              if (mb.byteLength > this.needed)
              {
                  this.buffers.unshift(mb.slice(this.needed));
                  mb = mb.slice(0, this.needed);
              }
              this.callback.call(this.sc, mb,
                          this.saved_msg_header || undefined);
          }
          
      },
  
      request: function(n)
      {
          this.needed = n;
      },
  
      save_header: function(h)
      {
          this.saved_msg_header = h;
      },
  
      clear_header: function()
      {
          this.saved_msg_header = undefined;
      },
  }
  
  function wire_blob_catcher(e)
  {
      DEBUG > 1 && console.log(">> WebSockets.onmessage");
      DEBUG > 1 && console.log("id " + this.wire_reader.sc.connection_id +"; type " + this.wire_reader.sc.type);
      SpiceWireReader.prototype.inbound.call(this.wire_reader, e.data);
  }