UNPKG

pb-websocket

Version:
1,826 lines (1,535 loc) 48 kB
'use strict'; var _create = require('babel-runtime/core-js/object/create'); var _create2 = _interopRequireDefault(_create); var _stringify = require('babel-runtime/core-js/json/stringify'); var _stringify2 = _interopRequireDefault(_stringify); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Require the given path. * * @param {String} path * @return {Object} exports * @api public */ function _require(path, parent, orig) { var resolved = _require.resolve(path); // lookup failed if (null == resolved) { orig = orig || path; parent = parent || 'root'; var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); err.path = orig; err.parent = parent; err.require = true; throw err; } var module = _require.modules[resolved]; // perform real require() // by invoking the module's // registered function if (!module._resolving && !module.exports) { var mod = {}; mod.exports = {}; mod.client = mod.component = true; module._resolving = true; module.call(this, mod.exports, _require.relative(resolved), mod); delete module._resolving; module.exports = mod.exports; } return module.exports; } /** * Registered modules. */ _require.modules = {}; /** * Registered aliases. */ _require.aliases = {}; /** * Resolve `path`. * * Lookup: * * - PATH/index.js * - PATH.js * - PATH * * @param {String} path * @return {String} path or null * @api private */ _require.resolve = function (path) { if (path.charAt(0) === '/') path = path.slice(1); var paths = [path, path + '.js', path + '.json', path + '/index.js', path + '/index.json']; for (var i = 0; i < paths.length; i++) { var path = paths[i]; if (_require.modules.hasOwnProperty(path)) return path; if (_require.aliases.hasOwnProperty(path)) return _require.aliases[path]; } }; /** * Normalize `path` relative to the current path. * * @param {String} curr * @param {String} path * @return {String} * @api private */ _require.normalize = function (curr, path) { var segs = []; if ('.' != path.charAt(0)) return path; curr = curr.split('/'); path = path.split('/'); for (var i = 0; i < path.length; ++i) { if ('..' == path[i]) { curr.pop(); } else if ('.' != path[i] && '' != path[i]) { segs.push(path[i]); } } return curr.concat(segs).join('/'); }; /** * Register module at `path` with callback `definition`. * * @param {String} path * @param {Function} definition * @api private */ _require.register = function (path, definition) { _require.modules[path] = definition; }; /** * Alias a module definition. * * @param {String} from * @param {String} to * @api private */ _require.alias = function (from, to) { if (!_require.modules.hasOwnProperty(from)) { throw new Error('Failed to alias "' + from + '", it does not exist'); } _require.aliases[to] = from; }; /** * Return a require function relative to the `parent` path. * * @param {String} parent * @return {Function} * @api private */ _require.relative = function (parent) { var p = _require.normalize(parent, '..'); /** * lastIndexOf helper. */ function lastIndexOf(arr, obj) { var i = arr.length; while (i--) { if (arr[i] === obj) return i; } return -1; } /** * The relative require() itself. */ function localRequire(path) { var resolved = localRequire.resolve(path); return _require(resolved, parent, path); } /** * Resolve relative to the parent. */ localRequire.resolve = function (path) { var c = path.charAt(0); if ('/' == c) return path.slice(1); if ('.' == c) return _require.normalize(p, path); // resolve deps by returning // the dep in the nearest "deps" // directory var segs = parent.split('/'); var i = lastIndexOf(segs, 'deps') + 1; if (!i) i = 0; path = segs.slice(0, i + 1).join('/') + '/deps/' + path; return path; }; /** * Check if module is defined at `path`. */ localRequire.exists = function (path) { return _require.modules.hasOwnProperty(localRequire.resolve(path)); }; return localRequire; }; _require.register("component-emitter/index.js", function (exports, require, module) { /** * Expose `Emitter`. */ module.exports = Emitter; /** * Initialize a new `Emitter`. * * @api public */ function Emitter(obj) { if (obj) return mixin(obj); }; /** * Mixin the emitter properties. * * @param {Object} obj * @return {Object} * @api private */ function mixin(obj) { for (var key in Emitter.prototype) { obj[key] = Emitter.prototype[key]; } return obj; } /** * Listen on the given `event` with `fn`. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.on = Emitter.prototype.addEventListener = function (event, fn) { this._callbacks = this._callbacks || {}; (this._callbacks[event] = this._callbacks[event] || []).push(fn); return this; }; /** * Adds an `event` listener that will be invoked a single * time then automatically removed. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.once = function (event, fn) { var self = this; this._callbacks = this._callbacks || {}; function on() { self.off(event, on); fn.apply(this, arguments); } on.fn = fn; this.on(event, on); return this; }; /** * Remove the given callback for `event` or all * registered callbacks. * * @param {String} event * @param {Function} fn * @return {Emitter} * @api public */ Emitter.prototype.off = Emitter.prototype.removeListener = Emitter.prototype.removeAllListeners = Emitter.prototype.removeEventListener = function (event, fn) { this._callbacks = this._callbacks || {}; // all if (0 == arguments.length) { this._callbacks = {}; return this; } // specific event var callbacks = this._callbacks[event]; if (!callbacks) return this; // remove all handlers if (1 == arguments.length) { delete this._callbacks[event]; return this; } // remove specific handler var cb; for (var i = 0; i < callbacks.length; i++) { cb = callbacks[i]; if (cb === fn || cb.fn === fn) { callbacks.splice(i, 1); break; } } return this; }; /** * Emit `event` with the given args. * * @param {String} event * @param {Mixed} ... * @return {Emitter} */ Emitter.prototype.emit = function (event) { this._callbacks = this._callbacks || {}; var args = [].slice.call(arguments, 1), callbacks = this._callbacks[event]; if (callbacks) { callbacks = callbacks.slice(0); for (var i = 0, len = callbacks.length; i < len; ++i) { callbacks[i].apply(this, args); } } return this; }; /** * Return array of callbacks for `event`. * * @param {String} event * @return {Array} * @api public */ Emitter.prototype.listeners = function (event) { this._callbacks = this._callbacks || {}; return this._callbacks[event] || []; }; /** * Check if this emitter has `event` handlers. * * @param {String} event * @return {Boolean} * @api public */ Emitter.prototype.hasListeners = function (event) { return !!this.listeners(event).length; }; }); _require.register("NetEase-pomelo-protocol/lib/protocol.js", function (exports, require, module) { (function (exports, ByteArray, window) { var Protocol = exports; var PKG_HEAD_BYTES = 4; var MSG_FLAG_BYTES = 1; var MSG_ROUTE_CODE_BYTES = 2; var MSG_ID_MAX_BYTES = 5; var MSG_ROUTE_LEN_BYTES = 1; var MSG_ROUTE_CODE_MAX = 0xffff; var MSG_COMPRESS_ROUTE_MASK = 0x1; var MSG_TYPE_MASK = 0x7; var Package = Protocol.Package = {}; var Message = Protocol.Message = {}; Package.TYPE_HANDSHAKE = 1; Package.TYPE_HANDSHAKE_ACK = 2; Package.TYPE_HEARTBEAT = 3; Package.TYPE_DATA = 4; Package.TYPE_KICK = 5; Message.TYPE_REQUEST = 0; Message.TYPE_NOTIFY = 1; Message.TYPE_RESPONSE = 2; Message.TYPE_PUSH = 3; /** * pomele client encode * id message id; * route message route * msg message body * socketio current support string */ Protocol.strencode = function (str) { var byteArray = new ByteArray(str.length * 3); var offset = 0; for (var i = 0; i < str.length; i++) { var charCode = str.charCodeAt(i); var codes = null; if (charCode <= 0x7f) { codes = [charCode]; } else if (charCode <= 0x7ff) { codes = [0xc0 | charCode >> 6, 0x80 | charCode & 0x3f]; } else { codes = [0xe0 | charCode >> 12, 0x80 | (charCode & 0xfc0) >> 6, 0x80 | charCode & 0x3f]; } for (var j = 0; j < codes.length; j++) { byteArray[offset] = codes[j]; ++offset; } } var _buffer = new ByteArray(offset); copyArray(_buffer, 0, byteArray, 0, offset); return _buffer; }; /** * client decode * msg String data * return Message Object */ Protocol.strdecode = function (buffer) { var bytes = new ByteArray(buffer); var array = []; var offset = 0; var charCode = 0; var end = bytes.length; while (offset < end) { if (bytes[offset] < 128) { charCode = bytes[offset]; offset += 1; } else if (bytes[offset] < 224) { charCode = ((bytes[offset] & 0x3f) << 6) + (bytes[offset + 1] & 0x3f); offset += 2; } else { charCode = ((bytes[offset] & 0x0f) << 12) + ((bytes[offset + 1] & 0x3f) << 6) + (bytes[offset + 2] & 0x3f); offset += 3; } array.push(charCode); } return String.fromCharCode.apply(null, array); }; /** * Package protocol encode. * * Pomelo package format: * +------+-------------+------------------+ * | type | body length | body | * +------+-------------+------------------+ * * Head: 4bytes * 0: package type, * 1 - handshake, * 2 - handshake ack, * 3 - heartbeat, * 4 - data * 5 - kick * 1 - 3: big-endian body length * Body: body length bytes * * @param {Number} type package type * @param {ByteArray} body body content in bytes * @return {ByteArray} new byte array that contains encode result */ Package.encode = function (type, body) { var length = body ? body.length : 0; var buffer = new ByteArray(PKG_HEAD_BYTES + length); var index = 0; buffer[index++] = type & 0xff; buffer[index++] = length >> 16 & 0xff; buffer[index++] = length >> 8 & 0xff; buffer[index++] = length & 0xff; if (body) { copyArray(buffer, index, body, 0, length); } return buffer; }; /** * Package protocol decode. * See encode for package format. * * @param {ByteArray} buffer byte array containing package content * @return {Object} {type: package type, buffer: body byte array} */ Package.decode = function (buffer) { var offset = 0; var bytes = new ByteArray(buffer); var length = 0; var rs = []; while (offset < bytes.length) { var type = bytes[offset++]; length = (bytes[offset++] << 16 | bytes[offset++] << 8 | bytes[offset++]) >>> 0; var body = length ? new ByteArray(length) : null; copyArray(body, 0, bytes, offset, length); offset += length; rs.push({ 'type': type, 'body': body }); } return rs.length === 1 ? rs[0] : rs; }; /** * Message protocol encode. * * @param {Number} id message id * @param {Number} type message type * @param {Number} compressRoute whether compress route * @param {Number|String} route route code or route string * @param {Buffer} msg message body bytes * @return {Buffer} encode result */ Message.encode = function (id, type, compressRoute, route, msg) { // caculate message max length var idBytes = msgHasId(type) ? caculateMsgIdBytes(id) : 0; var msgLen = MSG_FLAG_BYTES + idBytes; if (msgHasRoute(type)) { if (compressRoute) { if (typeof route !== 'number') { throw new Error('error flag for number route!'); } msgLen += MSG_ROUTE_CODE_BYTES; } else { msgLen += MSG_ROUTE_LEN_BYTES; if (route) { route = Protocol.strencode(route); if (route.length > 255) { throw new Error('route maxlength is overflow'); } msgLen += route.length; } } } if (msg) { msgLen += msg.length; } var buffer = new ByteArray(msgLen); var offset = 0; // add flag offset = encodeMsgFlag(type, compressRoute, buffer, offset); // add message id if (msgHasId(type)) { offset = encodeMsgId(id, buffer, offset); } // add route if (msgHasRoute(type)) { offset = encodeMsgRoute(compressRoute, route, buffer, offset); } // add body if (msg) { offset = encodeMsgBody(msg, buffer, offset); } return buffer; }; /** * Message protocol decode. * * @param {Buffer|Uint8Array} buffer message bytes * @return {Object} message object */ Message.decode = function (buffer) { var bytes = new ByteArray(buffer); var bytesLen = bytes.length || bytes.byteLength; var offset = 0; var id = 0; var route = null; // parse flag var flag = bytes[offset++]; var compressRoute = flag & MSG_COMPRESS_ROUTE_MASK; var type = flag >> 1 & MSG_TYPE_MASK; // parse id if (msgHasId(type)) { var m = parseInt(bytes[offset]); var i = 0; do { var m = parseInt(bytes[offset]); id = id + (m & 0x7f) * Math.pow(2, 7 * i); offset++; i++; } while (m >= 128); } // parse route if (msgHasRoute(type)) { if (compressRoute) { route = bytes[offset++] << 8 | bytes[offset++]; } else { var routeLen = bytes[offset++]; if (routeLen) { route = new ByteArray(routeLen); copyArray(route, 0, bytes, offset, routeLen); route = Protocol.strdecode(route); } else { route = ''; } offset += routeLen; } } // parse body var bodyLen = bytesLen - offset; var body = new ByteArray(bodyLen); copyArray(body, 0, bytes, offset, bodyLen); return { 'id': id, 'type': type, 'compressRoute': compressRoute, 'route': route, 'body': body }; }; var copyArray = function copyArray(dest, doffset, src, soffset, length) { if ('function' === typeof src.copy) { // Buffer src.copy(dest, doffset, soffset, soffset + length); } else { // Uint8Array for (var index = 0; index < length; index++) { dest[doffset++] = src[soffset++]; } } }; var msgHasId = function msgHasId(type) { return type === Message.TYPE_REQUEST || type === Message.TYPE_RESPONSE; }; var msgHasRoute = function msgHasRoute(type) { return type === Message.TYPE_REQUEST || type === Message.TYPE_NOTIFY || type === Message.TYPE_PUSH; }; var caculateMsgIdBytes = function caculateMsgIdBytes(id) { var len = 0; do { len += 1; id >>= 7; } while (id > 0); return len; }; var encodeMsgFlag = function encodeMsgFlag(type, compressRoute, buffer, offset) { if (type !== Message.TYPE_REQUEST && type !== Message.TYPE_NOTIFY && type !== Message.TYPE_RESPONSE && type !== Message.TYPE_PUSH) { throw new Error('unkonw message type: ' + type); } buffer[offset] = type << 1 | (compressRoute ? 1 : 0); return offset + MSG_FLAG_BYTES; }; var encodeMsgId = function encodeMsgId(id, buffer, offset) { do { var tmp = id % 128; var next = Math.floor(id / 128); if (next !== 0) { tmp = tmp + 128; } buffer[offset++] = tmp; id = next; } while (id !== 0); return offset; }; var encodeMsgRoute = function encodeMsgRoute(compressRoute, route, buffer, offset) { if (compressRoute) { if (route > MSG_ROUTE_CODE_MAX) { throw new Error('route number is overflow'); } buffer[offset++] = route >> 8 & 0xff; buffer[offset++] = route & 0xff; } else { if (route) { buffer[offset++] = route.length & 0xff; copyArray(buffer, offset, route, 0, route.length); offset += route.length; } else { buffer[offset++] = 0; } } return offset; }; var encodeMsgBody = function encodeMsgBody(msg, buffer, offset) { copyArray(buffer, offset, msg, 0, msg.length); return offset + msg.length; }; module.exports = Protocol; if (typeof window != "undefined") { window.Protocol = Protocol; } })(typeof window == "undefined" ? module.exports : window.Protocol = {}, typeof window == "undefined" ? Buffer : Uint8Array, window); }); _require.register("pomelonode-pomelo-protobuf/lib/client/protobuf.js", function (exports, require, module) { /* ProtocolBuffer client 0.1.0*/ /** * pomelo-protobuf * @author <zhang0935@gmail.com> */ /** * Protocol buffer root * In browser, it will be window.protbuf */ (function (exports, window) { var Protobuf = exports; Protobuf.init = function (opts) { //On the serverside, use serverProtos to encode messages send to client Protobuf.encoder.init(opts.encoderProtos); //On the serverside, user clientProtos to decode messages receive from clients Protobuf.decoder.init(opts.decoderProtos); }; Protobuf.encode = function (key, msg) { return Protobuf.encoder.encode(key, msg); }; Protobuf.decode = function (key, msg) { return Protobuf.decoder.decode(key, msg); }; // exports to support for components module.exports = Protobuf; if (typeof window != "undefined") { window.protobuf = Protobuf; } })(typeof window == "undefined" ? module.exports : window.protobuf = {}, window); /** * constants */ (function (exports, window) { var constants = exports.constants = {}; constants.TYPES = { uInt32: 0, sInt32: 0, int32: 0, double: 1, string: 2, message: 2, float: 5 }; })('undefined' !== typeof protobuf ? protobuf : module.exports, window); /** * util module */ (function (exports, window) { var Util = exports.util = {}; Util.isSimpleType = function (type) { return type === 'uInt32' || type === 'sInt32' || type === 'int32' || type === 'uInt64' || type === 'sInt64' || type === 'float' || type === 'double'; }; })('undefined' !== typeof protobuf ? protobuf : module.exports, window); /** * codec module */ (function (exports, window) { var Codec = exports.codec = {}; var buffer = new ArrayBuffer(8); var float32Array = new Float32Array(buffer); var float64Array = new Float64Array(buffer); var uInt8Array = new Uint8Array(buffer); Codec.encodeUInt32 = function (n) { var n = parseInt(n); if (isNaN(n) || n < 0) { return null; } var result = []; do { var tmp = n % 128; var next = Math.floor(n / 128); if (next !== 0) { tmp = tmp + 128; } result.push(tmp); n = next; } while (n !== 0); return result; }; Codec.encodeSInt32 = function (n) { var n = parseInt(n); if (isNaN(n)) { return null; } n = n < 0 ? Math.abs(n) * 2 - 1 : n * 2; return Codec.encodeUInt32(n); }; Codec.decodeUInt32 = function (bytes) { var n = 0; for (var i = 0; i < bytes.length; i++) { var m = parseInt(bytes[i]); n = n + (m & 0x7f) * Math.pow(2, 7 * i); if (m < 128) { return n; } } return n; }; Codec.decodeSInt32 = function (bytes) { var n = this.decodeUInt32(bytes); var flag = n % 2 === 1 ? -1 : 1; n = (n % 2 + n) / 2 * flag; return n; }; Codec.encodeFloat = function (float) { float32Array[0] = float; return uInt8Array; }; Codec.decodeFloat = function (bytes, offset) { if (!bytes || bytes.length < offset + 4) { return null; } for (var i = 0; i < 4; i++) { uInt8Array[i] = bytes[offset + i]; } return float32Array[0]; }; Codec.encodeDouble = function (double) { float64Array[0] = double; return uInt8Array.subarray(0, 8); }; Codec.decodeDouble = function (bytes, offset) { if (!bytes || bytes.length < offset + 8) { return null; } for (var i = 0; i < 8; i++) { uInt8Array[i] = bytes[offset + i]; } return float64Array[0]; }; Codec.encodeStr = function (bytes, offset, str) { for (var i = 0; i < str.length; i++) { var code = str.charCodeAt(i); var codes = encode2UTF8(code); for (var j = 0; j < codes.length; j++) { bytes[offset] = codes[j]; offset++; } } return offset; }; /** * Decode string from utf8 bytes */ Codec.decodeStr = function (bytes, offset, length) { var array = []; var end = offset + length; while (offset < end) { var code = 0; if (bytes[offset] < 128) { code = bytes[offset]; offset += 1; } else if (bytes[offset] < 224) { code = ((bytes[offset] & 0x3f) << 6) + (bytes[offset + 1] & 0x3f); offset += 2; } else { code = ((bytes[offset] & 0x0f) << 12) + ((bytes[offset + 1] & 0x3f) << 6) + (bytes[offset + 2] & 0x3f); offset += 3; } array.push(code); } var str = ''; for (var i = 0; i < array.length;) { str += String.fromCharCode.apply(null, array.slice(i, i + 10000)); i += 10000; } return str; }; /** * Return the byte length of the str use utf8 */ Codec.byteLength = function (str) { if (typeof str !== 'string') { return -1; } var length = 0; for (var i = 0; i < str.length; i++) { var code = str.charCodeAt(i); length += codeLength(code); } return length; }; /** * Encode a unicode16 char code to utf8 bytes */ function encode2UTF8(charCode) { if (charCode <= 0x7f) { return [charCode]; } else if (charCode <= 0x7ff) { return [0xc0 | charCode >> 6, 0x80 | charCode & 0x3f]; } else { return [0xe0 | charCode >> 12, 0x80 | (charCode & 0xfc0) >> 6, 0x80 | charCode & 0x3f]; } } function codeLength(code) { if (code <= 0x7f) { return 1; } else if (code <= 0x7ff) { return 2; } else { return 3; } } })('undefined' !== typeof protobuf ? protobuf : module.exports, window); /** * encoder module */ (function (exports, window) { var protobuf = exports; var MsgEncoder = exports.encoder = {}; var codec = protobuf.codec; var constant = protobuf.constants; var util = protobuf.util; MsgEncoder.init = function (protos) { this.protos = protos || {}; }; MsgEncoder.encode = function (route, msg) { //Get protos from protos map use the route as key var protos = this.protos[route]; //Check msg if (!checkMsg(msg, protos)) { return null; } //Set the length of the buffer 2 times bigger to prevent overflow var length = codec.byteLength((0, _stringify2.default)(msg)); //Init buffer and offset var buffer = new ArrayBuffer(length); var uInt8Array = new Uint8Array(buffer); var offset = 0; if (!!protos) { offset = encodeMsg(uInt8Array, offset, protos, msg); if (offset > 0) { return uInt8Array.subarray(0, offset); } } return null; }; /** * Check if the msg follow the defination in the protos */ function checkMsg(msg, protos) { if (!protos) { return false; } for (var name in protos) { var proto = protos[name]; //All required element must exist switch (proto.option) { case 'required': if (typeof msg[name] === 'undefined') { console.warn('no property exist for required! name: %j, proto: %j, msg: %j', name, proto, msg); return false; } case 'optional': if (typeof msg[name] !== 'undefined') { var message = protos.__messages[proto.type] || MsgEncoder.protos['message ' + proto.type]; if (!!message && !checkMsg(msg[name], message)) { console.warn('inner proto error! name: %j, proto: %j, msg: %j', name, proto, msg); return false; } } break; case 'repeated': //Check nest message in repeated elements var message = protos.__messages[proto.type] || MsgEncoder.protos['message ' + proto.type]; if (!!msg[name] && !!message) { for (var i = 0; i < msg[name].length; i++) { if (!checkMsg(msg[name][i], message)) { return false; } } } break; } } return true; } function encodeMsg(buffer, offset, protos, msg) { for (var name in msg) { if (!!protos[name]) { var proto = protos[name]; switch (proto.option) { case 'required': case 'optional': offset = writeBytes(buffer, offset, encodeTag(proto.type, proto.tag)); offset = encodeProp(msg[name], proto.type, offset, buffer, protos); break; case 'repeated': if (msg[name].length > 0) { offset = encodeArray(msg[name], proto, offset, buffer, protos); } break; } } } return offset; } function encodeProp(value, type, offset, buffer, protos) { switch (type) { case 'uInt32': offset = writeBytes(buffer, offset, codec.encodeUInt32(value)); break; case 'int32': case 'sInt32': offset = writeBytes(buffer, offset, codec.encodeSInt32(value)); break; case 'float': writeBytes(buffer, offset, codec.encodeFloat(value)); offset += 4; break; case 'double': writeBytes(buffer, offset, codec.encodeDouble(value)); offset += 8; break; case 'string': var length = codec.byteLength(value); //Encode length offset = writeBytes(buffer, offset, codec.encodeUInt32(length)); //write string codec.encodeStr(buffer, offset, value); offset += length; break; default: var message = protos.__messages[type] || MsgEncoder.protos['message ' + type]; if (!!message) { //Use a tmp buffer to build an internal msg var tmpBuffer = new ArrayBuffer(codec.byteLength((0, _stringify2.default)(value)) * 2); var length = 0; length = encodeMsg(tmpBuffer, length, message, value); //Encode length offset = writeBytes(buffer, offset, codec.encodeUInt32(length)); //contact the object for (var i = 0; i < length; i++) { buffer[offset] = tmpBuffer[i]; offset++; } } break; } return offset; } /** * Encode reapeated properties, simple msg and object are decode differented */ function encodeArray(array, proto, offset, buffer, protos) { var i = 0; if (util.isSimpleType(proto.type)) { offset = writeBytes(buffer, offset, encodeTag(proto.type, proto.tag)); offset = writeBytes(buffer, offset, codec.encodeUInt32(array.length)); for (i = 0; i < array.length; i++) { offset = encodeProp(array[i], proto.type, offset, buffer); } } else { for (i = 0; i < array.length; i++) { offset = writeBytes(buffer, offset, encodeTag(proto.type, proto.tag)); offset = encodeProp(array[i], proto.type, offset, buffer, protos); } } return offset; } function writeBytes(buffer, offset, bytes) { for (var i = 0; i < bytes.length; i++, offset++) { buffer[offset] = bytes[i]; } return offset; } function encodeTag(type, tag) { var value = constant.TYPES[type] || 2; return codec.encodeUInt32(tag << 3 | value); } })('undefined' !== typeof protobuf ? protobuf : module.exports, window); /** * decoder module */ (function (exports, window) { var protobuf = exports; var MsgDecoder = exports.decoder = {}; var codec = protobuf.codec; var util = protobuf.util; var buffer; var offset = 0; MsgDecoder.init = function (protos) { this.protos = protos || {}; }; MsgDecoder.setProtos = function (protos) { if (!!protos) { this.protos = protos; } }; MsgDecoder.decode = function (route, buf) { var protos = this.protos[route]; buffer = buf; offset = 0; if (!!protos) { return decodeMsg({}, protos, buffer.length); } return null; }; function decodeMsg(msg, protos, length) { while (offset < length) { var head = getHead(); var type = head.type; var tag = head.tag; var name = protos.__tags[tag]; switch (protos[name].option) { case 'optional': case 'required': msg[name] = decodeProp(protos[name].type, protos); break; case 'repeated': if (!msg[name]) { msg[name] = []; } decodeArray(msg[name], protos[name].type, protos); break; } } return msg; } /** * Test if the given msg is finished */ function isFinish(msg, protos) { return !protos.__tags[peekHead().tag]; } /** * Get property head from protobuf */ function getHead() { var tag = codec.decodeUInt32(getBytes()); return { type: tag & 0x7, tag: tag >> 3 }; } /** * Get tag head without move the offset */ function peekHead() { var tag = codec.decodeUInt32(peekBytes()); return { type: tag & 0x7, tag: tag >> 3 }; } function decodeProp(type, protos) { switch (type) { case 'uInt32': return codec.decodeUInt32(getBytes()); case 'int32': case 'sInt32': return codec.decodeSInt32(getBytes()); case 'float': var float = codec.decodeFloat(buffer, offset); offset += 4; return float; case 'double': var double = codec.decodeDouble(buffer, offset); offset += 8; return double; case 'string': var length = codec.decodeUInt32(getBytes()); var str = codec.decodeStr(buffer, offset, length); offset += length; return str; default: var message = protos && (protos.__messages[type] || MsgDecoder.protos['message ' + type]); if (!!message) { var length = codec.decodeUInt32(getBytes()); var msg = {}; decodeMsg(msg, message, offset + length); return msg; } break; } } function decodeArray(array, type, protos) { if (util.isSimpleType(type)) { var length = codec.decodeUInt32(getBytes()); for (var i = 0; i < length; i++) { array.push(decodeProp(type)); } } else { array.push(decodeProp(type, protos)); } } function getBytes(flag) { var bytes = []; var pos = offset; flag = flag || false; var b; do { b = buffer[pos]; bytes.push(b); pos++; } while (b >= 128); if (!flag) { offset = pos; } return bytes; } function peekBytes() { return getBytes(true); } })('undefined' !== typeof protobuf ? protobuf : module.exports, window); }); _require.register("pomelonode-pomelo-jsclient-websocket/lib/pomelo-client.js", function (exports, require, module) { (function () { var JS_WS_CLIENT_TYPE = 'js-websocket'; var JS_WS_CLIENT_VERSION = '0.0.1'; var Protocol = window.Protocol; var protobuf = window.protobuf; var decodeIO_protobuf = window.decodeIO_protobuf; var decodeIO_encoder = null; var decodeIO_decoder = null; var Package = Protocol.Package; var Message = Protocol.Message; var EventEmitter = window.EventEmitter; var rsa = window.rsa; if (typeof window != "undefined" && typeof sys != 'undefined' && sys.localStorage) { window.localStorage = sys.localStorage; } var RES_OK = 200; var RES_FAIL = 500; var RES_OLD_CLIENT = 501; if (typeof _create2.default !== 'function') { Object.create = function (o) { function F() {} F.prototype = o; return new F(); }; } var root = window; var pomelo = (0, _create2.default)(EventEmitter.prototype); // object extend from object root.pomelo = pomelo; var socket = null; var reqId = 0; var callbacks = {}; var handlers = {}; //Map from request id to route var routeMap = {}; var dict = {}; // route string to code var abbrs = {}; // code to route string var serverProtos = {}; var clientProtos = {}; var protoVersion = 0; var heartbeatInterval = 0; var heartbeatTimeout = 0; var nextHeartbeatTimeout = 0; var gapThreshold = 100; // heartbeat gap threashold var heartbeatId = null; var heartbeatTimeoutId = null; var handshakeCallback = null; var decode = null; var encode = null; var reconnect = false; var reconncetTimer = null; var reconnectUrl = null; var reconnectAttempts = 0; var reconnectionDelay = 5000; var DEFAULT_MAX_RECONNECT_ATTEMPTS = 10; var useCrypto; var handshakeBuffer = { 'sys': { type: JS_WS_CLIENT_TYPE, version: JS_WS_CLIENT_VERSION, rsa: {} }, 'user': {} }; var initCallback = null; pomelo.init = function (params, cb) { initCallback = cb; var host = params.host; var port = params.port; encode = params.encode || defaultEncode; decode = params.decode || defaultDecode; var url = 'ws://' + host; if (port) { url += ':' + port; } handshakeBuffer.user = params.user; if (params.encrypt) { useCrypto = true; rsa.generate(1024, "10001"); var data = { rsa_n: rsa.n.toString(16), rsa_e: rsa.e }; handshakeBuffer.sys.rsa = data; } handshakeCallback = params.handshakeCallback; connect(params, url, cb); }; var defaultDecode = pomelo.decode = function (data) { //probuff decode var msg = Message.decode(data); if (msg.id > 0) { msg.route = routeMap[msg.id]; delete routeMap[msg.id]; if (!msg.route) { return; } } msg.body = deCompose(msg); return msg; }; var defaultEncode = pomelo.encode = function (reqId, route, msg) { var type = reqId ? Message.TYPE_REQUEST : Message.TYPE_NOTIFY; //compress message by protobuf if (protobuf && clientProtos[route]) { msg = protobuf.encode(route, msg); } else if (decodeIO_encoder && decodeIO_encoder.lookup(route)) { var Builder = decodeIO_encoder.build(route); msg = new Builder(msg).encodeNB(); } else { msg = Protocol.strencode((0, _stringify2.default)(msg)); } var compressRoute = 0; if (dict && dict[route]) { route = dict[route]; compressRoute = 1; } return Message.encode(reqId, type, compressRoute, route, msg); }; var connect = function connect(params, url, cb) { console.log('connect to ' + url); var params = params || {}; var maxReconnectAttempts = params.maxReconnectAttempts || DEFAULT_MAX_RECONNECT_ATTEMPTS; reconnectUrl = url; //Add protobuf version if (window.localStorage && window.localStorage.getItem('protos') && protoVersion === 0) { var protos = JSON.parse(window.localStorage.getItem('protos')); protoVersion = protos.version || 0; serverProtos = protos.server || {}; clientProtos = protos.client || {}; if (!!protobuf) { protobuf.init({ encoderProtos: clientProtos, decoderProtos: serverProtos }); } if (!!decodeIO_protobuf) { decodeIO_encoder = decodeIO_protobuf.loadJson(clientProtos); decodeIO_decoder = decodeIO_protobuf.loadJson(serverProtos); } } //Set protoversion handshakeBuffer.sys.protoVersion = protoVersion; var onopen = function onopen(event) { if (!!reconnect) { pomelo.emit('reconnect'); } reset(); var obj = Package.encode(Package.TYPE_HANDSHAKE, Protocol.strencode((0, _stringify2.default)(handshakeBuffer))); send(obj); }; var onmessage = function onmessage(event) { processPackage(Package.decode(event.data), cb); // new package arrived, update the heartbeat timeout if (heartbeatTimeout) { nextHeartbeatTimeout = Date.now() + heartbeatTimeout; } }; var onerror = function onerror(event) { pomelo.emit('io-error', event); console.error('socket error: ', event); }; var onclose = function onclose(event) { pomelo.emit('close', event); pomelo.emit('disconnect', event); console.error('socket close: ', event); if (!!params.reconnect && reconnectAttempts < maxReconnectAttempts) { reconnect = true; reconnectAttempts++; reconncetTimer = setTimeout(function () { connect(params, reconnectUrl, cb); }, reconnectionDelay); reconnectionDelay *= 2; } }; socket = new WebSocket(url); socket.binaryType = 'arraybuffer'; socket.onopen = onopen; socket.onmessage = onmessage; socket.onerror = onerror; socket.onclose = onclose; }; pomelo.disconnect = function () { if (socket) { if (socket.disconnect) socket.disconnect(); if (socket.close) socket.close(); console.log('disconnect'); socket = null; } if (heartbeatId) { clearTimeout(heartbeatId); heartbeatId = null; } if (heartbeatTimeoutId) { clearTimeout(heartbeatTimeoutId); heartbeatTimeoutId = null; } }; var reset = function reset() { reconnect = false; reconnectionDelay = 1000 * 5; reconnectAttempts = 0; clearTimeout(reconncetTimer); }; pomelo.request = function (route, msg, cb) { if (arguments.length === 2 && typeof msg === 'function') { cb = msg; msg = {}; } else { msg = msg || {}; } route = route || msg.route; if (!route) { return; } reqId++; sendMessage(reqId, route, msg); callbacks[reqId] = cb; routeMap[reqId] = route; }; pomelo.notify = function (route, msg) { msg = msg || {}; sendMessage(0, route, msg); }; var sendMessage = function sendMessage(reqId, route, msg) { if (useCrypto) { msg = (0, _stringify2.default)(msg); var sig = rsa.signString(msg, "sha256"); msg = JSON.parse(msg); msg['__crypto__'] = sig; } if (encode) { msg = encode(reqId, route, msg); } var packet = Package.encode(Package.TYPE_DATA, msg); send(packet); }; var send = function send(packet) { socket.send(packet.buffer); }; var handler = {}; var heartbeat = function heartbeat(data) { if (!heartbeatInterval) { // no heartbeat return; } var obj = Package.encode(Package.TYPE_HEARTBEAT); if (heartbeatTimeoutId) { clearTimeout(heartbeatTimeoutId); heartbeatTimeoutId = null; } if (heartbeatId) { // already in a heartbeat interval return; } heartbeatId = setTimeout(function () { heartbeatId = null; send(obj); nextHeartbeatTimeout = Date.now() + heartbeatTimeout; heartbeatTimeoutId = setTimeout(heartbeatTimeoutCb, heartbeatTimeout); }, heartbeatInterval); }; var heartbeatTimeoutCb = function heartbeatTimeoutCb() { var gap = nextHeartbeatTimeout - Date.now(); if (gap > gapThreshold) { heartbeatTimeoutId = setTimeout(heartbeatTimeoutCb, gap); } else { console.error('server heartbeat timeout'); pomelo.emit('heartbeat timeout'); pomelo.disconnect(); } }; var handshake = function handshake(data) { data = JSON.parse(Protocol.strdecode(data)); if (data.code === RES_OLD_CLIENT) { pomelo.emit('error', 'client version not fullfill'); return; } if (data.code !== RES_OK) { pomelo.emit('error', 'handshake fail'); return; } handshakeInit(data); var obj = Package.encode(Package.TYPE_HANDSHAKE_ACK); send(obj); if (initCallback) { initCallback(socket); } }; var onData = function onData(data) { var msg = data; if (decode) { msg = decode(msg); } processMessage(pomelo, msg); }; var onKick = function onKick(data) { data = JSON.parse(Protocol.strdecode(data)); pomelo.emit('onKick', data); }; handlers[Package.TYPE_HANDSHAKE] = handshake; handlers[Package.TYPE_HEARTBEAT] = heartbeat; handlers[Package.TYPE_DATA] = onData; handlers[Package.TYPE_KICK] = onKick; var processPackage = function processPackage(msgs) { if (Array.isArray(msgs)) { for (var i = 0; i < msgs.length; i++) { var msg = msgs[i]; handlers[msg.type](msg.body); } } else { handlers[msgs.type](msgs.body); } }; var processMessage = function processMessage(pomelo, msg) { if (!msg.id) { // server push message pomelo.emit(msg.route, msg.body); return; } //if have a id then find the callback function with the request var cb = callbacks[msg.id]; delete callbacks[msg.id]; if (typeof cb !== 'function') { return; } cb(msg.body); return; }; var processMessageBatch = function processMessageBatch(pomelo, msgs) { for (var i = 0, l = msgs.length; i < l; i++) { processMessage(pomelo, msgs[i]); } }; var deCompose = function deCompose(msg) { var route = msg.route; //Decompose route from dict if (msg.compressRoute) { if (!abbrs[route]) { return {}; } route = msg.route = abbrs[route]; } if (protobuf && serverProtos[route]) { return protobuf.decode(route, msg.body); } else if (decodeIO_decoder && decodeIO_decoder.lookup(route)) { return decodeIO_decoder.build(route).decode(msg.body); } else { return JSON.parse(Protocol.strdecode(msg.body)); } return msg; }; var handshakeInit = function handshakeInit(data) { if (data.sys && data.sys.heartbeat) { heartbeatInterval = data.sys.heartbeat * 1000; // heartbeat interval heartbeatTimeout = heartbeatInterval * 2; // max heartbeat timeout } else { heartbeatInterval = 0; heartbeatTimeout = 0; } initData(data); if (typeof handshakeCallback === 'function') { handshakeCallback(data.user); } }; //Initilize data used in pomelo client var initData = function initData(data) { if (!data || !data.sys) { return; } dict = data.sys.dict; var protos = data.sys.protos; //Init compress dict if (dict) { dict = dict; abbrs = {}; for (var route in dict) { abbrs[dict[route]] = route; } } //Init protobuf protos if (protos) { protoVersion = protos.version || 0; serverProtos = protos.server || {}; clientProtos = protos.client || {}; //Save protobuf protos to localStorage window.localStorage.setItem('protos', (0, _stringify2.default)(protos)); if (!!protobuf) { protobuf.init({ encoderProtos: protos.client, decoderProtos: protos.server }); } if (!!decodeIO_protobuf) { decodeIO_encoder = decodeIO_protobuf.loadJson(clientProtos); decodeIO_decoder = decodeIO_protobuf.loadJson(serverProtos); } } }; module.exports = pomelo; })(); }); _require.register("boot/index.js", function (exports, require, module) { var Emitter = require('emitter'); window.EventEmitter = Emitter; var protocol = require('pomelo-protocol'); window.Protocol = protocol; var protobuf = require('pomelo-protobuf'); window.protobuf = protobuf; var pomelo = require('pomelo-jsclient-websocket'); window.pomelo = pomelo; }); _require.alias("boot/index.js", "pomelo-client/deps/boot/index.js"); _require.alias("boot/index.js", "boot/index.js"); _require.alias("component-emitter/index.js", "boot/deps/emitter/index.js"); _require.alias("NetEase-pomelo-protocol/lib/protocol.js", "boot/deps/pomelo-protocol/lib/protocol.js"); _require.alias("NetEase-pomelo-protocol/lib/protocol.js", "boot/deps/pomelo-protocol/index.js"); _require.alias("NetEase-pomelo-protocol/lib/protocol.js", "NetEase-pomelo-protocol/index.js"); _require.alias("pomelonode-pomelo-protobuf/lib/client/protobuf.js", "boot/deps/pomelo-protobuf/lib/client/protobuf.js"); _require.alias("pomelonode-pomelo-protobuf/lib/client/protobuf.js", "boot/deps/pomelo-protobuf/index.js"); _require.alias("pomelonode-pomelo-protobuf/lib/client/protobuf.js", "pomelonode-pomelo-protobuf/index.js"); _require.alias("pomelonode-pomelo-jsclient-websocket/lib/pomelo-client.js", "boot/deps/pomelo-jsclient-websocket/lib/pomelo-client.js"); _require.alias("pomelonode-pomelo-jsclient-websocket/lib/pomelo-client.js", "boot/deps/pomelo-jsclient-websocket/index.js"); _require.alias("pomelonode-pomelo-jsclient-websocket/lib/pomelo-client.js", "pomelonode-pomelo-jsclient-websocket/index.js"); _require('boot'); exports.pomelo = pomelo;