@@ -11,6 +11,11 @@ var Socket = require('simple-websocket')
1111
1212var common = require ( './common' )
1313
14+ // Use a socket pool, so tracker clients share WebSocket objects for the same server.
15+ // In practice, WebSockets are pretty slow to establish, so this gives a nice performance
16+ // boost, and saves browser resources.
17+ var socketPool = { }
18+
1419var RECONNECT_VARIANCE = 30 * 1000
1520var RECONNECT_MINIMUM = 5 * 1000
1621
@@ -26,9 +31,10 @@ function WebSocketTracker (client, announceUrl, opts) {
2631
2732 self . _opts = opts
2833
34+ if ( announceUrl [ announceUrl . length - 1 ] === '/' ) {
35+ announceUrl = announceUrl . substring ( 0 , announceUrl . length - 1 )
36+ }
2937 self . _announceUrl = announceUrl
30- if ( self . _announceUrl [ self . _announceUrl . length - 1 ] !== '/' ) self . _announceUrl += '/'
31- self . _announceUrl += '?' + hat ( 40 )
3238
3339 self . _peers = { } // peers (offer id -> peer)
3440 self . _socket = null
@@ -102,7 +108,11 @@ WebSocketTracker.prototype._openSocket = function () {
102108 self . _onSocketDataBound = self . _onSocketData . bind ( self )
103109 self . _onSocketCloseBound = self . _onSocketClose . bind ( self )
104110
105- self . _socket = new Socket ( self . _announceUrl )
111+ self . _socket = socketPool [ self . _announceUrl ]
112+ if ( ! self . _socket ) {
113+ self . _socket = socketPool [ self . _announceUrl ] = new Socket ( self . _announceUrl )
114+ }
115+
106116 self . _socket . on ( 'data' , self . _onSocketDataBound )
107117 self . _socket . on ( 'close' , self . _onSocketCloseBound )
108118 self . _socket . on ( 'error' , self . _onSocketErrorBound )
@@ -117,10 +127,22 @@ WebSocketTracker.prototype._onSocketData = function (data) {
117127 }
118128
119129 if ( data . info_hash !== self . client . _infoHashBinary ) {
120- return self . client . emit ( 'warning' , new Error ( 'Invalid tracker response' ) )
130+ debug (
131+ 'ignoring websocket data from %s for %s (looking for %s: reused socket)' ,
132+ self . _announceUrl , common . binaryToHex ( data . info_hash ) , self . client . _infoHashHex
133+ )
134+ return
121135 }
122136
123- debug ( 'received %s from %s' , JSON . stringify ( data ) , self . _announceUrl )
137+ if ( data . peer_id && data . peer_id === self . client . _peerIdBinary ) {
138+ // ignore offers/answers from this client
139+ return
140+ }
141+
142+ debug (
143+ 'received %s from %s for %s' ,
144+ JSON . stringify ( data ) , self . _announceUrl , self . client . _infoHashHex
145+ )
124146
125147 var failure = data [ 'failure reason' ]
126148 if ( failure ) return self . client . emit ( 'warning' , new Error ( failure ) )
@@ -149,13 +171,8 @@ WebSocketTracker.prototype._onSocketData = function (data) {
149171 } )
150172 }
151173
152- if ( self . client . _peerIdHex === common . binaryToHex ( data . peer_id ) ) {
153- // ignore offers/answers from this client
154- return
155- }
156-
157174 var peer
158- if ( data . offer ) {
175+ if ( data . offer && data . peer_id ) {
159176 peer = new Peer ( {
160177 trickle : false ,
161178 config : self . client . _rtcConfig ,
@@ -177,7 +194,7 @@ WebSocketTracker.prototype._onSocketData = function (data) {
177194 self . client . emit ( 'peer' , peer )
178195 }
179196
180- if ( data . answer ) {
197+ if ( data . answer && data . peer_id ) {
181198 peer = self . _peers [ common . binaryToHex ( data . offer_id ) ]
182199 if ( peer ) {
183200 peer . id = common . binaryToHex ( data . peer_id )
@@ -191,18 +208,28 @@ WebSocketTracker.prototype._onSocketData = function (data) {
191208
192209WebSocketTracker . prototype . _onSocketClose = function ( ) {
193210 var self = this
211+ if ( self . destroyed ) return
194212 self . destroy ( )
195- var ms = Math . floor ( Math . random ( ) * RECONNECT_VARIANCE ) + RECONNECT_MINIMUM
196- setTimeout ( function ( ) {
197- self . _openSocket ( )
198- } , ms )
199- debug ( 'reconnecting socket in %s ms' , ms )
213+ self . _startReconnectTimer ( )
200214}
201215
202216WebSocketTracker . prototype . _onSocketError = function ( err ) {
203217 var self = this
204218 if ( self . destroyed ) return
205- self . client . emit ( 'error' , err )
219+ self . destroy ( )
220+ // errors will often happen if a tracker is offline, so don't treat it as fatal
221+ self . client . emit ( 'warning' , err )
222+ self . _startReconnectTimer ( )
223+ }
224+
225+ WebSocketTracker . prototype . _startReconnectTimer = function ( ) {
226+ var self = this
227+ var ms = Math . floor ( Math . random ( ) * RECONNECT_VARIANCE ) + RECONNECT_MINIMUM
228+ setTimeout ( function ( ) {
229+ self . destroyed = false
230+ self . _openSocket ( )
231+ } , ms )
232+ debug ( 'reconnecting socket in %s ms' , ms )
206233}
207234
208235WebSocketTracker . prototype . _send = function ( params ) {
0 commit comments