stomp-1.7.1.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. // Generated by CoffeeScript 1.7.1
  2. /*
  3. Stomp Over WebSocket http://www.jmesnil.net/stomp-websocket/doc/ | Apache License V2.0
  4. Copyright (C) 2010-2013 [Jeff Mesnil](http://jmesnil.net/)
  5. Copyright (C) 2012 [FuseSource, Inc.](http://fusesource.com)
  6. */
  7. (function() {
  8. var Byte, Client, Frame, Stomp,
  9. __hasProp = {}.hasOwnProperty,
  10. __slice = [].slice;
  11. Byte = {
  12. LF: '\x0A',
  13. NULL: '\x00'
  14. };
  15. Frame = (function() {
  16. var unmarshallSingle;
  17. function Frame(command, headers, body) {
  18. this.command = command;
  19. this.headers = headers != null ? headers : {};
  20. this.body = body != null ? body : '';
  21. }
  22. Frame.prototype.toString = function() {
  23. var lines, name, value, _ref;
  24. lines = [this.command];
  25. _ref = this.headers;
  26. for (name in _ref) {
  27. if (!__hasProp.call(_ref, name)) continue;
  28. value = _ref[name];
  29. lines.push("" + name + ":" + value);
  30. }
  31. if (this.body) {
  32. lines.push("content-length:" + (Frame.sizeOfUTF8(this.body)));
  33. }
  34. lines.push(Byte.LF + this.body);
  35. return lines.join(Byte.LF);
  36. };
  37. Frame.sizeOfUTF8 = function(s) {
  38. if (s) {
  39. return encodeURI(s).split(/%..|./).length - 1;
  40. } else {
  41. return 0;
  42. }
  43. };
  44. unmarshallSingle = function(data) {
  45. var body, chr, command, divider, headerLines, headers, i, idx, len, line, start, trim, _i, _j, _len, _ref, _ref1;
  46. divider = data.search(RegExp("" + Byte.LF + Byte.LF));
  47. headerLines = data.substring(0, divider).split(Byte.LF);
  48. command = headerLines.shift();
  49. headers = {};
  50. trim = function(str) {
  51. return str.replace(/^\s+|\s+$/g, '');
  52. };
  53. _ref = headerLines.reverse();
  54. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  55. line = _ref[_i];
  56. idx = line.indexOf(':');
  57. headers[trim(line.substring(0, idx))] = trim(line.substring(idx + 1));
  58. }
  59. body = '';
  60. start = divider + 2;
  61. if (headers['content-length']) {
  62. len = parseInt(headers['content-length']);
  63. body = ('' + data).substring(start, start + len);
  64. } else {
  65. chr = null;
  66. for (i = _j = start, _ref1 = data.length; start <= _ref1 ? _j < _ref1 : _j > _ref1; i = start <= _ref1 ? ++_j : --_j) {
  67. chr = data.charAt(i);
  68. if (chr === Byte.NULL) {
  69. break;
  70. }
  71. body += chr;
  72. }
  73. }
  74. return new Frame(command, headers, body);
  75. };
  76. Frame.unmarshall = function(datas) {
  77. var data;
  78. return (function() {
  79. var _i, _len, _ref, _results;
  80. _ref = datas.split(RegExp("" + Byte.NULL + Byte.LF + "*"));
  81. _results = [];
  82. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  83. data = _ref[_i];
  84. if ((data != null ? data.length : void 0) > 0) {
  85. _results.push(unmarshallSingle(data));
  86. }
  87. }
  88. return _results;
  89. })();
  90. };
  91. Frame.marshall = function(command, headers, body) {
  92. var frame;
  93. frame = new Frame(command, headers, body);
  94. return frame.toString() + Byte.NULL;
  95. };
  96. return Frame;
  97. })();
  98. Client = (function() {
  99. var now;
  100. function Client(ws) {
  101. this.ws = ws;
  102. this.ws.binaryType = "arraybuffer";
  103. this.counter = 0;
  104. this.connected = false;
  105. this.heartbeat = {
  106. outgoing: 10000,
  107. incoming: 10000
  108. };
  109. this.maxWebSocketFrameSize = 16 * 1024;
  110. this.subscriptions = {};
  111. }
  112. Client.prototype.debug = function(message) {
  113. var _ref;
  114. return typeof window !== "undefined" && window !== null ? (_ref = window.console) != null ? _ref.log(message) : void 0 : void 0;
  115. };
  116. now = function() {
  117. return Date.now || new Date().valueOf;
  118. };
  119. Client.prototype._transmit = function(command, headers, body) {
  120. var out;
  121. out = Frame.marshall(command, headers, body);
  122. if (typeof this.debug === "function") {
  123. this.debug(">>> " + out);
  124. }
  125. while (true) {
  126. if (out.length > this.maxWebSocketFrameSize) {
  127. this.ws.send(out.substring(0, this.maxWebSocketFrameSize));
  128. out = out.substring(this.maxWebSocketFrameSize);
  129. if (typeof this.debug === "function") {
  130. this.debug("remaining = " + out.length);
  131. }
  132. } else {
  133. return this.ws.send(out);
  134. }
  135. }
  136. };
  137. Client.prototype._setupHeartbeat = function(headers) {
  138. var serverIncoming, serverOutgoing, ttl, v, _ref, _ref1;
  139. if ((_ref = headers.version) !== Stomp.VERSIONS.V1_1 && _ref !== Stomp.VERSIONS.V1_2) {
  140. return;
  141. }
  142. _ref1 = (function() {
  143. var _i, _len, _ref1, _results;
  144. _ref1 = headers['heart-beat'].split(",");
  145. _results = [];
  146. for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
  147. v = _ref1[_i];
  148. _results.push(parseInt(v));
  149. }
  150. return _results;
  151. })(), serverOutgoing = _ref1[0], serverIncoming = _ref1[1];
  152. if (!(this.heartbeat.outgoing === 0 || serverIncoming === 0)) {
  153. ttl = Math.max(this.heartbeat.outgoing, serverIncoming);
  154. if (typeof this.debug === "function") {
  155. this.debug("send PING every " + ttl + "ms");
  156. }
  157. this.pinger = Stomp.setInterval(ttl, (function(_this) {
  158. return function() {
  159. _this.ws.send(Byte.LF);
  160. return typeof _this.debug === "function" ? _this.debug(">>> PING") : void 0;
  161. };
  162. })(this));
  163. }
  164. if (!(this.heartbeat.incoming === 0 || serverOutgoing === 0)) {
  165. ttl = Math.max(this.heartbeat.incoming, serverOutgoing);
  166. if (typeof this.debug === "function") {
  167. this.debug("check PONG every " + ttl + "ms");
  168. }
  169. return this.ponger = Stomp.setInterval(ttl, (function(_this) {
  170. return function() {
  171. var delta;
  172. delta = now() - _this.serverActivity;
  173. if (delta > ttl * 2) {
  174. if (typeof _this.debug === "function") {
  175. _this.debug("did not receive server activity for the last " + delta + "ms");
  176. }
  177. return _this.ws.close();
  178. }
  179. };
  180. })(this));
  181. }
  182. };
  183. Client.prototype._parseConnect = function() {
  184. var args, connectCallback, errorCallback, headers;
  185. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  186. headers = {};
  187. switch (args.length) {
  188. case 2:
  189. headers = args[0], connectCallback = args[1];
  190. break;
  191. case 3:
  192. if (args[1] instanceof Function) {
  193. headers = args[0], connectCallback = args[1], errorCallback = args[2];
  194. } else {
  195. headers.login = args[0], headers.passcode = args[1], connectCallback = args[2];
  196. }
  197. break;
  198. case 4:
  199. headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3];
  200. break;
  201. default:
  202. headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3], headers.host = args[4];
  203. }
  204. return [headers, connectCallback, errorCallback];
  205. };
  206. Client.prototype.connect = function() {
  207. var args, errorCallback, headers, out;
  208. args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
  209. out = this._parseConnect.apply(this, args);
  210. headers = out[0], this.connectCallback = out[1], errorCallback = out[2];
  211. if (typeof this.debug === "function") {
  212. this.debug("Opening Web Socket...");
  213. }
  214. this.ws.onmessage = (function(_this) {
  215. return function(evt) {
  216. var arr, c, client, data, frame, messageID, onreceive, subscription, _i, _len, _ref, _results;
  217. 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() {
  218. var _i, _len, _results;
  219. _results = [];
  220. for (_i = 0, _len = arr.length; _i < _len; _i++) {
  221. c = arr[_i];
  222. _results.push(String.fromCharCode(c));
  223. }
  224. return _results;
  225. })()).join('')) : evt.data;
  226. _this.serverActivity = now();
  227. if (data === Byte.LF) {
  228. if (typeof _this.debug === "function") {
  229. _this.debug("<<< PONG");
  230. }
  231. return;
  232. }
  233. if (typeof _this.debug === "function") {
  234. _this.debug("<<< " + data);
  235. }
  236. _ref = Frame.unmarshall(data);
  237. _results = [];
  238. for (_i = 0, _len = _ref.length; _i < _len; _i++) {
  239. frame = _ref[_i];
  240. switch (frame.command) {
  241. case "CONNECTED":
  242. if (typeof _this.debug === "function") {
  243. _this.debug("connected to server " + frame.headers.server);
  244. }
  245. _this.connected = true;
  246. _this._setupHeartbeat(frame.headers);
  247. _results.push(typeof _this.connectCallback === "function" ? _this.connectCallback(frame) : void 0);
  248. break;
  249. case "MESSAGE":
  250. subscription = frame.headers.subscription;
  251. onreceive = _this.subscriptions[subscription] || _this.onreceive;
  252. if (onreceive) {
  253. client = _this;
  254. messageID = frame.headers["message-id"];
  255. frame.ack = function(headers) {
  256. if (headers == null) {
  257. headers = {};
  258. }
  259. return client.ack(messageID, subscription, headers);
  260. };
  261. frame.nack = function(headers) {
  262. if (headers == null) {
  263. headers = {};
  264. }
  265. return client.nack(messageID, subscription, headers);
  266. };
  267. _results.push(onreceive(frame));
  268. } else {
  269. _results.push(typeof _this.debug === "function" ? _this.debug("Unhandled received MESSAGE: " + frame) : void 0);
  270. }
  271. break;
  272. case "RECEIPT":
  273. _results.push(typeof _this.onreceipt === "function" ? _this.onreceipt(frame) : void 0);
  274. break;
  275. case "ERROR":
  276. _results.push(typeof errorCallback === "function" ? errorCallback(frame) : void 0);
  277. break;
  278. default:
  279. _results.push(typeof _this.debug === "function" ? _this.debug("Unhandled frame: " + frame) : void 0);
  280. }
  281. }
  282. return _results;
  283. };
  284. })(this);
  285. this.ws.onclose = (function(_this) {
  286. return function() {
  287. var msg;
  288. msg = "Whoops! Lost connection to " + _this.ws.url;
  289. if (typeof _this.debug === "function") {
  290. _this.debug(msg);
  291. }
  292. _this._cleanUp();
  293. return typeof errorCallback === "function" ? errorCallback(msg) : void 0;
  294. };
  295. })(this);
  296. return this.ws.onopen = (function(_this) {
  297. return function() {
  298. if (typeof _this.debug === "function") {
  299. _this.debug('Web Socket Opened...');
  300. }
  301. headers["accept-version"] = Stomp.VERSIONS.supportedVersions();
  302. headers["heart-beat"] = [_this.heartbeat.outgoing, _this.heartbeat.incoming].join(',');
  303. return _this._transmit("CONNECT", headers);
  304. };
  305. })(this);
  306. };
  307. Client.prototype.disconnect = function(disconnectCallback) {
  308. this._transmit("DISCONNECT");
  309. this.ws.onclose = null;
  310. this.ws.close();
  311. this._cleanUp();
  312. return typeof disconnectCallback === "function" ? disconnectCallback() : void 0;
  313. };
  314. Client.prototype._cleanUp = function() {
  315. this.connected = false;
  316. if (this.pinger) {
  317. Stomp.clearInterval(this.pinger);
  318. }
  319. if (this.ponger) {
  320. return Stomp.clearInterval(this.ponger);
  321. }
  322. };
  323. Client.prototype.send = function(destination, headers, body) {
  324. if (headers == null) {
  325. headers = {};
  326. }
  327. if (body == null) {
  328. body = '';
  329. }
  330. headers.destination = destination;
  331. return this._transmit("SEND", headers, body);
  332. };
  333. Client.prototype.subscribe = function(destination, callback, headers) {
  334. var client;
  335. if (headers == null) {
  336. headers = {};
  337. }
  338. if (!headers.id) {
  339. headers.id = "sub-" + this.counter++;
  340. }
  341. headers.destination = destination;
  342. this.subscriptions[headers.id] = callback;
  343. this._transmit("SUBSCRIBE", headers);
  344. client = this;
  345. return {
  346. id: headers.id,
  347. unsubscribe: function() {
  348. return client.unsubscribe(headers.id);
  349. }
  350. };
  351. };
  352. Client.prototype.unsubscribe = function(id) {
  353. delete this.subscriptions[id];
  354. return this._transmit("UNSUBSCRIBE", {
  355. id: id
  356. });
  357. };
  358. Client.prototype.begin = function(transaction) {
  359. var client, txid;
  360. txid = transaction || "tx-" + this.counter++;
  361. this._transmit("BEGIN", {
  362. transaction: txid
  363. });
  364. client = this;
  365. return {
  366. id: txid,
  367. commit: function() {
  368. return client.commit(txid);
  369. },
  370. abort: function() {
  371. return client.abort(txid);
  372. }
  373. };
  374. };
  375. Client.prototype.commit = function(transaction) {
  376. return this._transmit("COMMIT", {
  377. transaction: transaction
  378. });
  379. };
  380. Client.prototype.abort = function(transaction) {
  381. return this._transmit("ABORT", {
  382. transaction: transaction
  383. });
  384. };
  385. Client.prototype.ack = function(messageID, subscription, headers) {
  386. if (headers == null) {
  387. headers = {};
  388. }
  389. headers["message-id"] = messageID;
  390. headers.subscription = subscription;
  391. return this._transmit("ACK", headers);
  392. };
  393. Client.prototype.nack = function(messageID, subscription, headers) {
  394. if (headers == null) {
  395. headers = {};
  396. }
  397. headers["message-id"] = messageID;
  398. headers.subscription = subscription;
  399. return this._transmit("NACK", headers);
  400. };
  401. return Client;
  402. })();
  403. Stomp = {
  404. VERSIONS: {
  405. V1_0: '1.0',
  406. V1_1: '1.1',
  407. V1_2: '1.2',
  408. supportedVersions: function() {
  409. return '1.1,1.0';
  410. }
  411. },
  412. client: function(url, protocols) {
  413. var klass, ws;
  414. if (protocols == null) {
  415. protocols = ['v10.stomp', 'v11.stomp'];
  416. }
  417. klass = Stomp.WebSocketClass || WebSocket;
  418. ws = new klass(url, protocols);
  419. return new Client(ws);
  420. },
  421. over: function(ws) {
  422. return new Client(ws);
  423. },
  424. Frame: Frame
  425. };
  426. if (typeof window !== "undefined" && window !== null) {
  427. Stomp.setInterval = function(interval, f) {
  428. return window.setInterval(f, interval);
  429. };
  430. Stomp.clearInterval = function(id) {
  431. return window.clearInterval(id);
  432. };
  433. window.Stomp = Stomp;
  434. } else if (typeof exports !== "undefined" && exports !== null) {
  435. exports.Stomp = Stomp;
  436. } else {
  437. self.Stomp = Stomp;
  438. }
  439. }).call(this);