2015-01-05 07:45:36 -05:00
/ *
* Licensed to the Apache Software Foundation ( ASF ) under one
* or more contributor license agreements . See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership . The ASF licenses this file
* to you under the Apache License , Version 2.0 ( the
* "License" ) ; you may not use this file except in compliance
* with the License . You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing ,
* software distributed under the License is distributed on an
* "AS IS" BASIS , WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND , either express or implied . See the License for the
* specific language governing permissions and limitations
* under the License .
* /
2014-10-31 06:20:28 -04:00
( function ( ) {
var Byte , Client , Frame , Stomp ,
2017-09-20 12:01:14 -04:00
_ _hasProp = { } . hasOwnProperty ,
_ _slice = [ ] . slice ;
2014-10-31 06:20:28 -04:00
Byte = {
LF : '\x0A' ,
NULL : '\x00'
} ;
Frame = ( function ( ) {
2017-09-20 12:01:14 -04:00
var unmarshallSingle ;
2014-10-31 06:20:28 -04:00
function Frame ( command , headers , body ) {
this . command = command ;
this . headers = headers != null ? headers : { } ;
this . body = body != null ? body : '' ;
}
Frame . prototype . toString = function ( ) {
2017-09-20 12:01:14 -04:00
var lines , name , skipContentLength , value , _ref ;
2014-10-31 06:20:28 -04:00
lines = [ this . command ] ;
2017-09-20 12:01:14 -04:00
skipContentLength = this . headers [ 'content-length' ] === false ? true : false ;
if ( skipContentLength ) {
delete this . headers [ 'content-length' ] ;
}
2014-10-31 06:20:28 -04:00
_ref = this . headers ;
for ( name in _ref ) {
if ( ! _ _hasProp . call ( _ref , name ) ) continue ;
value = _ref [ name ] ;
lines . push ( "" + name + ":" + value ) ;
}
2017-09-20 12:01:14 -04:00
if ( this . body && ! skipContentLength ) {
lines . push ( "content-length:" + ( Frame . sizeOfUTF8 ( this . body ) ) ) ;
2014-10-31 06:20:28 -04:00
}
lines . push ( Byte . LF + this . body ) ;
return lines . join ( Byte . LF ) ;
} ;
2017-09-20 12:01:14 -04:00
Frame . sizeOfUTF8 = function ( s ) {
if ( s ) {
return encodeURI ( s ) . match ( /%..|./g ) . length ;
} else {
return 0 ;
}
} ;
unmarshallSingle = function ( data ) {
var body , chr , command , divider , headerLines , headers , i , idx , len , line , start , trim , _i , _j , _len , _ref , _ref1 ;
2014-10-31 06:20:28 -04:00
divider = data . search ( RegExp ( "" + Byte . LF + Byte . LF ) ) ;
headerLines = data . substring ( 0 , divider ) . split ( Byte . LF ) ;
command = headerLines . shift ( ) ;
headers = { } ;
trim = function ( str ) {
return str . replace ( /^\s+|\s+$/g , '' ) ;
} ;
2017-09-20 12:01:14 -04:00
_ref = headerLines . reverse ( ) ;
for ( _i = 0 , _len = _ref . length ; _i < _len ; _i ++ ) {
line = _ref [ _i ] ;
2014-10-31 06:20:28 -04:00
idx = line . indexOf ( ':' ) ;
headers [ trim ( line . substring ( 0 , idx ) ) ] = trim ( line . substring ( idx + 1 ) ) ;
}
body = '' ;
start = divider + 2 ;
if ( headers [ 'content-length' ] ) {
len = parseInt ( headers [ 'content-length' ] ) ;
body = ( '' + data ) . substring ( start , start + len ) ;
} else {
chr = null ;
for ( i = _j = start , _ref1 = data . length ; start <= _ref1 ? _j < _ref1 : _j > _ref1 ; i = start <= _ref1 ? ++ _j : -- _j ) {
chr = data . charAt ( i ) ;
if ( chr === Byte . NULL ) {
break ;
}
body += chr ;
}
}
return new Frame ( command , headers , body ) ;
} ;
Frame . unmarshall = function ( datas ) {
2017-09-20 12:01:14 -04:00
var frame , frames , last _frame , r ;
frames = datas . split ( RegExp ( "" + Byte . NULL + Byte . LF + "*" ) ) ;
r = {
frames : [ ] ,
partial : ''
} ;
r . frames = ( function ( ) {
2014-10-31 06:20:28 -04:00
var _i , _len , _ref , _results ;
2017-09-20 12:01:14 -04:00
_ref = frames . slice ( 0 , - 1 ) ;
2014-10-31 06:20:28 -04:00
_results = [ ] ;
for ( _i = 0 , _len = _ref . length ; _i < _len ; _i ++ ) {
2017-09-20 12:01:14 -04:00
frame = _ref [ _i ] ;
_results . push ( unmarshallSingle ( frame ) ) ;
2014-10-31 06:20:28 -04:00
}
return _results ;
} ) ( ) ;
2017-09-20 12:01:14 -04:00
last _frame = frames . slice ( - 1 ) [ 0 ] ;
if ( last _frame === Byte . LF || ( last _frame . search ( RegExp ( "" + Byte . NULL + Byte . LF + "*$" ) ) ) !== - 1 ) {
r . frames . push ( unmarshallSingle ( last _frame ) ) ;
} else {
r . partial = last _frame ;
}
return r ;
2014-10-31 06:20:28 -04:00
} ;
Frame . marshall = function ( command , headers , body ) {
var frame ;
frame = new Frame ( command , headers , body ) ;
return frame . toString ( ) + Byte . NULL ;
} ;
return Frame ;
} ) ( ) ;
Client = ( function ( ) {
2017-09-20 12:01:14 -04:00
var now ;
2014-10-31 06:20:28 -04:00
function Client ( ws ) {
this . ws = ws ;
this . ws . binaryType = "arraybuffer" ;
this . counter = 0 ;
this . connected = false ;
this . heartbeat = {
outgoing : 10000 ,
incoming : 10000
} ;
2017-09-20 12:01:14 -04:00
this . maxWebSocketFrameSize = 16 * 1024 ;
2014-10-31 06:20:28 -04:00
this . subscriptions = { } ;
2017-09-20 12:01:14 -04:00
this . partialData = '' ;
2014-10-31 06:20:28 -04:00
}
2017-09-20 12:01:14 -04:00
Client . prototype . debug = function ( message ) {
var _ref ;
return typeof window !== "undefined" && window !== null ? ( _ref = window . console ) != null ? _ref . log ( message ) : void 0 : void 0 ;
} ;
now = function ( ) {
if ( Date . now ) {
return Date . now ( ) ;
} else {
return new Date ( ) . valueOf ;
}
} ;
2014-10-31 06:20:28 -04:00
Client . prototype . _transmit = function ( command , headers , body ) {
var out ;
out = Frame . marshall ( command , headers , body ) ;
if ( typeof this . debug === "function" ) {
this . debug ( ">>> " + out ) ;
}
2017-09-20 12:01:14 -04:00
while ( true ) {
if ( out . length > this . maxWebSocketFrameSize ) {
this . ws . send ( out . substring ( 0 , this . maxWebSocketFrameSize ) ) ;
out = out . substring ( this . maxWebSocketFrameSize ) ;
if ( typeof this . debug === "function" ) {
this . debug ( "remaining = " + out . length ) ;
}
} else {
return this . ws . send ( out ) ;
}
}
2014-10-31 06:20:28 -04:00
} ;
Client . prototype . _setupHeartbeat = function ( headers ) {
2017-09-20 12:01:14 -04:00
var serverIncoming , serverOutgoing , ttl , v , _ref , _ref1 ;
2014-10-31 06:20:28 -04:00
if ( ( _ref = headers . version ) !== Stomp . VERSIONS . V1 _1 && _ref !== Stomp . VERSIONS . V1 _2 ) {
return ;
}
_ref1 = ( function ( ) {
var _i , _len , _ref1 , _results ;
_ref1 = headers [ 'heart-beat' ] . split ( "," ) ;
_results = [ ] ;
for ( _i = 0 , _len = _ref1 . length ; _i < _len ; _i ++ ) {
v = _ref1 [ _i ] ;
_results . push ( parseInt ( v ) ) ;
}
return _results ;
} ) ( ) , serverOutgoing = _ref1 [ 0 ] , serverIncoming = _ref1 [ 1 ] ;
if ( ! ( this . heartbeat . outgoing === 0 || serverIncoming === 0 ) ) {
ttl = Math . max ( this . heartbeat . outgoing , serverIncoming ) ;
if ( typeof this . debug === "function" ) {
this . debug ( "send PING every " + ttl + "ms" ) ;
}
2017-09-20 12:01:14 -04:00
this . pinger = Stomp . setInterval ( ttl , ( function ( _this ) {
return function ( ) {
_this . ws . send ( Byte . LF ) ;
return typeof _this . debug === "function" ? _this . debug ( ">>> PING" ) : void 0 ;
} ;
} ) ( this ) ) ;
2014-10-31 06:20:28 -04:00
}
if ( ! ( this . heartbeat . incoming === 0 || serverOutgoing === 0 ) ) {
ttl = Math . max ( this . heartbeat . incoming , serverOutgoing ) ;
if ( typeof this . debug === "function" ) {
this . debug ( "check PONG every " + ttl + "ms" ) ;
}
2017-09-20 12:01:14 -04:00
return this . ponger = Stomp . setInterval ( ttl , ( function ( _this ) {
return function ( ) {
var delta ;
delta = now ( ) - _this . serverActivity ;
if ( delta > ttl * 2 ) {
if ( typeof _this . debug === "function" ) {
_this . debug ( "did not receive server activity for the last " + delta + "ms" ) ;
}
return _this . ws . close ( ) ;
2014-10-31 06:20:28 -04:00
}
2017-09-20 12:01:14 -04:00
} ;
} ) ( this ) ) ;
}
} ;
Client . prototype . _parseConnect = function ( ) {
var args , connectCallback , errorCallback , headers ;
args = 1 <= arguments . length ? _ _slice . call ( arguments , 0 ) : [ ] ;
headers = { } ;
switch ( args . length ) {
case 2 :
headers = args [ 0 ] , connectCallback = args [ 1 ] ;
break ;
case 3 :
if ( args [ 1 ] instanceof Function ) {
headers = args [ 0 ] , connectCallback = args [ 1 ] , errorCallback = args [ 2 ] ;
} else {
headers . login = args [ 0 ] , headers . passcode = args [ 1 ] , connectCallback = args [ 2 ] ;
2014-10-31 06:20:28 -04:00
}
2017-09-20 12:01:14 -04:00
break ;
case 4 :
headers . login = args [ 0 ] , headers . passcode = args [ 1 ] , connectCallback = args [ 2 ] , errorCallback = args [ 3 ] ;
break ;
default :
headers . login = args [ 0 ] , headers . passcode = args [ 1 ] , connectCallback = args [ 2 ] , errorCallback = args [ 3 ] , headers . host = args [ 4 ] ;
2014-10-31 06:20:28 -04:00
}
2017-09-20 12:01:14 -04:00
return [ headers , connectCallback , errorCallback ] ;
2014-10-31 06:20:28 -04:00
} ;
2017-09-20 12:01:14 -04:00
Client . prototype . connect = function ( ) {
var args , errorCallback , headers , out ;
args = 1 <= arguments . length ? _ _slice . call ( arguments , 0 ) : [ ] ;
out = this . _parseConnect . apply ( this , args ) ;
headers = out [ 0 ] , this . connectCallback = out [ 1 ] , errorCallback = out [ 2 ] ;
2014-10-31 06:20:28 -04:00
if ( typeof this . debug === "function" ) {
this . debug ( "Opening Web Socket..." ) ;
}
2017-09-20 12:01:14 -04:00
this . ws . onmessage = ( function ( _this ) {
return function ( evt ) {
var arr , c , client , data , frame , messageID , onreceive , subscription , unmarshalledData , _i , _len , _ref , _results ;
data = typeof ArrayBuffer !== 'undefined' && evt . data instanceof ArrayBuffer ? ( arr = new Uint8Array ( evt . data ) , typeof _this . debug === "function" ? _this . debug ( "--- got data length: " + arr . length ) : void 0 , ( ( function ( ) {
var _i , _len , _results ;
_results = [ ] ;
for ( _i = 0 , _len = arr . length ; _i < _len ; _i ++ ) {
c = arr [ _i ] ;
_results . push ( String . fromCharCode ( c ) ) ;
}
return _results ;
} ) ( ) ) . join ( '' ) ) : evt . data ;
_this . serverActivity = now ( ) ;
if ( data === Byte . LF ) {
if ( typeof _this . debug === "function" ) {
_this . debug ( "<<< PONG" ) ;
}
return ;
}
if ( typeof _this . debug === "function" ) {
_this . debug ( "<<< " + data ) ;
}
unmarshalledData = Frame . unmarshall ( _this . partialData + data ) ;
_this . partialData = unmarshalledData . partial ;
_ref = unmarshalledData . frames ;
2014-10-31 06:20:28 -04:00
_results = [ ] ;
2017-09-20 12:01:14 -04:00
for ( _i = 0 , _len = _ref . length ; _i < _len ; _i ++ ) {
frame = _ref [ _i ] ;
switch ( frame . command ) {
case "CONNECTED" :
if ( typeof _this . debug === "function" ) {
_this . debug ( "connected to server " + frame . headers . server ) ;
}
_this . connected = true ;
_this . _setupHeartbeat ( frame . headers ) ;
_results . push ( typeof _this . connectCallback === "function" ? _this . connectCallback ( frame ) : void 0 ) ;
break ;
case "MESSAGE" :
subscription = frame . headers . subscription ;
onreceive = _this . subscriptions [ subscription ] || _this . onreceive ;
if ( onreceive ) {
client = _this ;
messageID = frame . headers [ "message-id" ] ;
frame . ack = function ( headers ) {
if ( headers == null ) {
headers = { } ;
}
return client . ack ( messageID , subscription , headers ) ;
} ;
frame . nack = function ( headers ) {
if ( headers == null ) {
headers = { } ;
}
return client . nack ( messageID , subscription , headers ) ;
} ;
_results . push ( onreceive ( frame ) ) ;
} else {
_results . push ( typeof _this . debug === "function" ? _this . debug ( "Unhandled received MESSAGE: " + frame ) : void 0 ) ;
}
break ;
case "RECEIPT" :
_results . push ( typeof _this . onreceipt === "function" ? _this . onreceipt ( frame ) : void 0 ) ;
break ;
case "ERROR" :
_results . push ( typeof errorCallback === "function" ? errorCallback ( frame ) : void 0 ) ;
break ;
default :
_results . push ( typeof _this . debug === "function" ? _this . debug ( "Unhandled frame: " + frame ) : void 0 ) ;
}
2014-10-31 06:20:28 -04:00
}
return _results ;
2017-09-20 12:01:14 -04:00
} ;
} ) ( this ) ;
this . ws . onclose = ( function ( _this ) {
return function ( ) {
var msg ;
msg = "Whoops! Lost connection to " + _this . ws . url ;
2014-10-31 06:20:28 -04:00
if ( typeof _this . debug === "function" ) {
2017-09-20 12:01:14 -04:00
_this . debug ( msg ) ;
2014-10-31 06:20:28 -04:00
}
2017-09-20 12:01:14 -04:00
_this . _cleanUp ( ) ;
return typeof errorCallback === "function" ? errorCallback ( msg ) : void 0 ;
} ;
} ) ( this ) ;
return this . ws . onopen = ( function ( _this ) {
return function ( ) {
if ( typeof _this . debug === "function" ) {
_this . debug ( 'Web Socket Opened...' ) ;
2014-10-31 06:20:28 -04:00
}
2017-09-20 12:01:14 -04:00
headers [ "accept-version" ] = Stomp . VERSIONS . supportedVersions ( ) ;
headers [ "heart-beat" ] = [ _this . heartbeat . outgoing , _this . heartbeat . incoming ] . join ( ',' ) ;
return _this . _transmit ( "CONNECT" , headers ) ;
2014-10-31 06:20:28 -04:00
} ;
2017-09-20 12:01:14 -04:00
} ) ( this ) ;
2014-10-31 06:20:28 -04:00
} ;
2017-09-20 12:01:14 -04:00
Client . prototype . disconnect = function ( disconnectCallback , headers ) {
if ( headers == null ) {
headers = { } ;
}
this . _transmit ( "DISCONNECT" , headers ) ;
2014-10-31 06:20:28 -04:00
this . ws . onclose = null ;
2017-09-20 12:01:14 -04:00
this . ws . close ( ) ;
2014-10-31 06:20:28 -04:00
this . _cleanUp ( ) ;
return typeof disconnectCallback === "function" ? disconnectCallback ( ) : void 0 ;
} ;
Client . prototype . _cleanUp = function ( ) {
this . connected = false ;
if ( this . pinger ) {
2017-09-20 12:01:14 -04:00
Stomp . clearInterval ( this . pinger ) ;
2014-10-31 06:20:28 -04:00
}
if ( this . ponger ) {
2017-09-20 12:01:14 -04:00
return Stomp . clearInterval ( this . ponger ) ;
2014-10-31 06:20:28 -04:00
}
} ;
Client . prototype . send = function ( destination , headers , body ) {
if ( headers == null ) {
headers = { } ;
}
if ( body == null ) {
body = '' ;
}
headers . destination = destination ;
return this . _transmit ( "SEND" , headers , body ) ;
} ;
Client . prototype . subscribe = function ( destination , callback , headers ) {
2017-09-20 12:01:14 -04:00
var client ;
2014-10-31 06:20:28 -04:00
if ( headers == null ) {
headers = { } ;
}
if ( ! headers . id ) {
headers . id = "sub-" + this . counter ++ ;
}
headers . destination = destination ;
this . subscriptions [ headers . id ] = callback ;
this . _transmit ( "SUBSCRIBE" , headers ) ;
2017-09-20 12:01:14 -04:00
client = this ;
return {
id : headers . id ,
unsubscribe : function ( ) {
return client . unsubscribe ( headers . id ) ;
}
} ;
2014-10-31 06:20:28 -04:00
} ;
Client . prototype . unsubscribe = function ( id ) {
delete this . subscriptions [ id ] ;
return this . _transmit ( "UNSUBSCRIBE" , {
id : id
} ) ;
} ;
Client . prototype . begin = function ( transaction ) {
2017-09-20 12:01:14 -04:00
var client , txid ;
txid = transaction || "tx-" + this . counter ++ ;
this . _transmit ( "BEGIN" , {
transaction : txid
2014-10-31 06:20:28 -04:00
} ) ;
2017-09-20 12:01:14 -04:00
client = this ;
return {
id : txid ,
commit : function ( ) {
return client . commit ( txid ) ;
} ,
abort : function ( ) {
return client . abort ( txid ) ;
}
} ;
2014-10-31 06:20:28 -04:00
} ;
Client . prototype . commit = function ( transaction ) {
return this . _transmit ( "COMMIT" , {
transaction : transaction
} ) ;
} ;
Client . prototype . abort = function ( transaction ) {
return this . _transmit ( "ABORT" , {
transaction : transaction
} ) ;
} ;
Client . prototype . ack = function ( messageID , subscription , headers ) {
if ( headers == null ) {
headers = { } ;
}
headers [ "message-id" ] = messageID ;
headers . subscription = subscription ;
return this . _transmit ( "ACK" , headers ) ;
} ;
Client . prototype . nack = function ( messageID , subscription , headers ) {
if ( headers == null ) {
headers = { } ;
}
headers [ "message-id" ] = messageID ;
headers . subscription = subscription ;
return this . _transmit ( "NACK" , headers ) ;
} ;
return Client ;
} ) ( ) ;
Stomp = {
VERSIONS : {
V1 _0 : '1.0' ,
V1 _1 : '1.1' ,
V1 _2 : '1.2' ,
supportedVersions : function ( ) {
return '1.1,1.0' ;
}
} ,
client : function ( url , protocols ) {
var klass , ws ;
if ( protocols == null ) {
protocols = [ 'v10.stomp' , 'v11.stomp' ] ;
}
klass = Stomp . WebSocketClass || WebSocket ;
ws = new klass ( url , protocols ) ;
return new Client ( ws ) ;
} ,
over : function ( ws ) {
return new Client ( ws ) ;
} ,
Frame : Frame
} ;
2017-09-20 12:01:14 -04:00
if ( typeof exports !== "undefined" && exports !== null ) {
exports . Stomp = Stomp ;
}
2014-10-31 06:20:28 -04:00
if ( typeof window !== "undefined" && window !== null ) {
2017-09-20 12:01:14 -04:00
Stomp . setInterval = function ( interval , f ) {
return window . setInterval ( f , interval ) ;
} ;
Stomp . clearInterval = function ( id ) {
return window . clearInterval ( id ) ;
} ;
2014-10-31 06:20:28 -04:00
window . Stomp = Stomp ;
2017-09-20 12:01:14 -04:00
} else if ( ! exports ) {
self . Stomp = Stomp ;
2014-10-31 06:20:28 -04:00
}
2017-09-20 12:01:14 -04:00
} ) . call ( this ) ;