From 2347fd0e1938be5db6bfc9a4e62bcec7322ebc16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BF=9C=E6=96=B9=E5=A4=95=E9=98=B3?= <3979434@qq.com> Date: Tue, 21 Aug 2018 21:10:43 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E7=9B=B8=E5=85=B3=E6=96=87?= =?UTF-8?q?=E6=A1=A3=E4=BB=A5=E5=8F=8A=E5=A2=9E=E5=8A=A0js=E7=89=88?= =?UTF-8?q?=E6=9C=AC=E7=9A=84protobuf=E7=BB=93=E6=9E=84=E4=BD=93=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 3.4.0.VERSION => 3.5.0.VERSION | 0 README.md | 224 +-- doc/WebSDK使用文档.doc | Bin 30720 -> 31232 bytes doc/{ => proto/java}/Message.proto | 0 doc/{ => proto/java}/ReplyBody.proto | 0 doc/{ => proto/java}/SentBody.proto | 0 doc/proto/java/说明.txt | 1 + doc/proto/js/Message.proto | 14 + doc/proto/js/ReplyBody.proto | 11 + doc/proto/js/SentBody.proto | 10 + doc/proto/js/message.js | 2728 ++++++++++++++++++++++++++ doc/proto/js/replybody.js | 2622 +++++++++++++++++++++++++ doc/proto/js/sentbody.js | 2568 ++++++++++++++++++++++++ doc/proto/js/说明.txt | 4 + 说明.txt | 11 +- 15 files changed, 8003 insertions(+), 190 deletions(-) rename 3.4.0.VERSION => 3.5.0.VERSION (100%) rename doc/{ => proto/java}/Message.proto (100%) rename doc/{ => proto/java}/ReplyBody.proto (100%) rename doc/{ => proto/java}/SentBody.proto (100%) create mode 100644 doc/proto/java/说明.txt create mode 100644 doc/proto/js/Message.proto create mode 100644 doc/proto/js/ReplyBody.proto create mode 100644 doc/proto/js/SentBody.proto create mode 100644 doc/proto/js/message.js create mode 100644 doc/proto/js/replybody.js create mode 100644 doc/proto/js/sentbody.js create mode 100644 doc/proto/js/说明.txt diff --git a/3.4.0.VERSION b/3.5.0.VERSION similarity index 100% rename from 3.4.0.VERSION rename to 3.5.0.VERSION diff --git a/README.md b/README.md index d27b654..c89c2cf 100644 --- a/README.md +++ b/README.md @@ -1,200 +1,48 @@ -### 说明: -此开源版本为基础功能版本,只有消息推送的基础功能!netty版本,和mina版本结构和功能完全一致,大家可以选择自己喜欢的或者合适的版本学习或者使用! +#### 项目介绍 +CIM是一套基于apache mina和Netty框架下的推送系统,平时我们一直使用第三方的推送SDK,比如极光,百度推送,小米推送,以及腾讯信鸽等来支撑自己的移动端的业务,或许有一些企业有着自己一套即时通讯系统的需求,那么CIM为您提供了一个解决方案,目前CIM支撑 webcokset,android,ios,桌面应用,系统应用等多端接入支持,CIM服务端使用springboot搭建仅仅拥有消息推送的功能,关于数据缓存与持久化都需要使用者自己开发,并且配备了比较完整的使用文档。希望能为您带来一些价值。 + -### 侣信专业版2.5.0版本发布 -### [http://farsunset.com](http://farsunset.com) +#### 目录说明 + +1. cim_for_mina目录下为mina版本实现 +2. cim_for_netty目录下为netty版本实现 +3. doc目录中是相关使用文档,以及protubuf结构体文件 +5. cim-android-sdk 是android客户端封装的的jar包 +6. cim-java-sdk 是java版客户端封装的的jar包 +7. cim-server-sdk 是cim-server 用到的封装的jar +8. cim-boot-server是springboot服务端工程,是eclipse4.x基于gradle构建插件 +9. cim-client-android 是android客户端 android studio工具 +10. 说明.txt是服务端环境搭建说明 + + +#### 建议反馈 + +智者千虑必有一失,如果再使用中发现任何问题或者有优化建议,您可以通过QQ3979434或者 邮箱3979434@qq.com向我反馈,当然目前还缺少IOS客户端sdk和.net客户端SDK,如果您有兴趣可以参与开发,CIM将会越来越好。 -### 前言: +#### 相关项目 - 现在市面上有很多 xmpp协议的即时通讯方案,openfire androidpn,等等。它们都是使用了apache mina开发,但是这些东西基本都需要二次改造开发。而且改动还很大,我也看过这些东西的源码,发现代码结构不太理想,耦合的情况太多,实在不好扩展。所谓XMPP 协议。只不过是别人使用mina 自定义了一个消息编码解码协议。通俗的讲就是,xml形式消息的编码与解码,我们完全没有必要在国外这套不成熟的openfire 与xmpp 上耗费过多的精力去研究,我们完全可以通过apache mina 自定义自己的通讯协议,并可以为它使用自己的名字。我们不要盲目崇拜国外的有些东西,自己掌握原理,才是最重要的,各位切记~ +侣信专业版是基于CIM面向中小企业和者各类团队组织内部交流使用工具。具有丰富的功能,聊天,群组,部门组织,内部朋友圈等功能。它可以在局域网内使用保证沟通的信息安全,并且它是完全免费的,而且可以及时获得更新。 +#### [http://farsunset.com](http://farsunset.com) - 这套IM系统为我个人自主开发 使用了 apache mina ,主要功能为 服务端和客户端,客户端 到客户端的即时通信,可以支持包括文字 图片,语音等任何消息形式 服务端使用的 struts2+spring3和 apache mina android端 也使用的apache mina。这套IM系统结构还是非常清晰合理的,非常容易扩展和改造,下面是android版本 的 demo的目的是只是一个演示 ,可以参照它的代码,使用这套系统开发自己的东西,核心价值是一套高灵活性,相对标准化的即时通讯解决方案,即时聊天只是它的一种运用途径! - - -### 服务端集群配置方案 -## 服务端修改 -1.多台服务器集群配置,首先需要重写SessionManager接口(参考com.farsunset.ichat.cim.session.ClusterSessionManager.java),用户登录时,将账号和服务器IP 存入数据库中,这样就可以统计各台服务器接受的连接数量。 -2.客户端连接服务器时,服务端为客户端动态分配 服务器IP,每次分配 较为空闲的服务器IP -3.服务端接受消息后 通过接收者账号查询出对应的Iosession,和 登录的 服务器IP,然后将消息信息传往目标服务器处理发送 - - -### 客户端端修改 -1.客户端登录时将不在是固定的服务器IP 而是先通过http接口获取到当前空闲的服务器IP,然后登录 - -### 成功案例 -### http://blog.csdn.net/xx753277/article/details/17512255 -### http://blog.csdn.net/xx753277/article/details/45535981 - - - - -### 客户端接收消息 -![image](http://staticres.oss-cn-hangzhou.aliyuncs.com/cim-android_client.png) - -### 服务端消息 web入口 -### http://192.168.1.11:8080/ichat-server +#### 功能预览 +1.控制台页面 ![image](http://staticres.oss-cn-hangzhou.aliyuncs.com/cim-server.png) +2.Android客户端 +![image](http://staticres.oss-cn-hangzhou.aliyuncs.com/cim-android_client.png) +3.Web客户端 +![image](http://staticres.oss-cn-hangzhou.aliyuncs.com/cim-server-message.png) +#### 更新日志 +------------------------------------------------------------------------------------------- +版本:3.5.0/时间:2018-08-22 -### 常用功能接口 -所有开放外部接口都集中在 -com.farsunset.cim.client.android.CIMPushManager +1.服务端由原来的 spring+struts2修改为springboot工程 + +2.全面重新websocket的实现,全面拥抱protobuf替换josn序列化方式,更加高效 -#### 1.1连接服务器 -```java -/** -* 初始化,连接服务端,在程序启动页或者 在Application里调用 -* @param context -* @param ip -* @param port -*/ -public static void connect(Context context,String ip,int port) - -//示例 -CIMPushManager.connect(context,"125.12.35.231",28888); - -``` - -#### 1.2绑定账号到服务端 -```java -/** -* 设置一个账号登录到服务端 -* @param account 用户唯一ID -*/ -public static void bindAccount(Context context,String account) - -//示例 -CIMPushManager.bindAccount(context,"xiyang"); - - -``` - -#### 1.3发送一个CIM请求 - - 酌情使用此功能,可用http接口替代 -```java -/** -* 发送一个CIM请求 -* @param context -* @param body 请求体的结构 -*/ -public static void sendRequest(Context context,SentBody body) - -//示例:获取离线消息 -SentBody sent = new SentBody(); -sent.setKey(CIMConstant.RequestKey.CLIENT_OFFLINE_MESSAGE); -sent.put("account", "xiyang"); -CIMPushManager.sendRequest(context, sent); - -//该功能需要服务端实现,详情参考服务端PullOflineMessageHandler.java - -``` - -#### 1.4停止接收消息 -```java -/** -* 停止接受推送,将会退出当前账号登录,端口与服务端的连接 -* @param context -*/ -public static void stop(Context context) -//示例: -CIMPushManager.stop(context); - -``` -#### 1.5恢复接收消息 -```java -/** -* 重新恢复接收推送,重新连接服务端,并登录当前账号 -* @param context -*/ -public static void resume(Context context) -//示例: -CIMPushManager.resume(context); -``` - - -#### 1.6完全销毁连接 -```java -/** -* 完全销毁CIM,一般用于完全退出程序,调用resume将不能恢复 -* @param context -*/ -public static void destroy(Context context) -//示例: -CIMPushManager.destroy(context); - - -``` -#### 1.7获取是否与服务端连接正常 -```java - -/** - * - * @param context - */ -public boolean isConnected(Context context) - -//示例: -CIMPushManager.isConnected(context); -``` - -#### 1.8获取PushManager状态 -```java -//被销毁的destroy() -CIMPushManager.STATE_DESTROYED = 0x0000DE; -//被销停止的 stop() -CIMPushManager.STATE_STOPED = 0x0000EE; - -CIMPushManager.STATE_NORMAL = 0x000000; - -public int getState(Context context) - -//示例: -CIMPushManager.getState(context); -``` - -#### 1.9推送消息以及相关事件的接收 - -首先注册一个广播,并监听以下action 参照 后面androidManifest.xml配置 - -参考CustomCIMMessageReceiver的实现 -```java -/** -* 当收到服务端推送过来的消息时调用 -* @param message -*/ -public abstract void onMessageReceived(Message message); - -/** -* 当调用CIMPushManager.sendRequest()向服务端发送请求,获得相应时调用 -* @param replybody -*/ -public abstract void onReplyReceived(ReplyBody replybody); - -/** -* 当手机网络发生变化时调用 -* @param networkinfo -*/ -public abstract void onNetworkChanged(NetworkInfo networkinfo); - -/** -* 当连接服务器成功时回调 -* @param hasAutoBind : true 已经自动绑定账号到服务器了,不需要再手动调用bindAccount -*/ -public abstract void onConnectionSuccessed(boolean hasAutoBind); - -/** -* 当断开服务器连接的时候回调 -*/ -public abstract void onConnectionClosed(); - -/** -* 当服务器连接失败的时候回调 -* -*/ -public abstract void onConnectionFailed(Exception e); -``` \ No newline at end of file + + \ No newline at end of file diff --git a/doc/WebSDK使用文档.doc b/doc/WebSDK使用文档.doc index 944ca7aa15cf7806efdf85c4f0a1dcc24fcb68e4..7b4ccfa516f911f647a08eec1199881cecf8c77e 100644 GIT binary patch delta 7445 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 H?3nOBlTbg^ delta 7658 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 diff --git a/doc/Message.proto b/doc/proto/java/Message.proto similarity index 100% rename from doc/Message.proto rename to doc/proto/java/Message.proto diff --git a/doc/ReplyBody.proto b/doc/proto/java/ReplyBody.proto similarity index 100% rename from doc/ReplyBody.proto rename to doc/proto/java/ReplyBody.proto diff --git a/doc/SentBody.proto b/doc/proto/java/SentBody.proto similarity index 100% rename from doc/SentBody.proto rename to doc/proto/java/SentBody.proto diff --git a/doc/proto/java/说明.txt b/doc/proto/java/说明.txt new file mode 100644 index 0000000..a9f7dfc --- /dev/null +++ b/doc/proto/java/说明.txt @@ -0,0 +1 @@ +ʹprotoc ɶӦjavaļ֮ǰ޸protoļеϢ \ No newline at end of file diff --git a/doc/proto/js/Message.proto b/doc/proto/js/Message.proto new file mode 100644 index 0000000..205d87a --- /dev/null +++ b/doc/proto/js/Message.proto @@ -0,0 +1,14 @@ +syntax = "proto3"; +package com.farsunset.cim.sdk.web.model; +message Message { + string mid = 1; + string action = 2; + string content = 3; + string sender = 4; + string receiver = 5; + string extra = 6; + string title = 7; + string format = 8; + int64 timestamp = 9; +} + \ No newline at end of file diff --git a/doc/proto/js/ReplyBody.proto b/doc/proto/js/ReplyBody.proto new file mode 100644 index 0000000..5e8af8c --- /dev/null +++ b/doc/proto/js/ReplyBody.proto @@ -0,0 +1,11 @@ +syntax = "proto3"; +package com.farsunset.cim.sdk.web.model; +message ReplyBody { + string key = 1; + string code = 2; + string message = 3; + int64 timestamp =4; + map data =5; + +} + \ No newline at end of file diff --git a/doc/proto/js/SentBody.proto b/doc/proto/js/SentBody.proto new file mode 100644 index 0000000..45d7e4d --- /dev/null +++ b/doc/proto/js/SentBody.proto @@ -0,0 +1,10 @@ +syntax = "proto3"; +package com.farsunset.cim.sdk.web.model; + +message SentBody { + string key = 1; + int64 timestamp =2; + map data =3; + +} + \ No newline at end of file diff --git a/doc/proto/js/message.js b/doc/proto/js/message.js new file mode 100644 index 0000000..644e760 --- /dev/null +++ b/doc/proto/js/message.js @@ -0,0 +1,2728 @@ +(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i, eg, foo.pb_default. + * For the list of reserved names please see: + * com.google.apps.jspb.JsClassTemplate.JS_RESERVED_WORDS. + * @param {boolean=} opt_includeInstance Whether to include the JSPB instance + * for transitional soy proto support: http://goto/soy-param-migration + * @return {!Object} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.toObject = function(opt_includeInstance) { + return proto.com.farsunset.cim.sdk.web.model.Message.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Whether to include the JSPB + * instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.com.farsunset.cim.sdk.web.model.Message} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.com.farsunset.cim.sdk.web.model.Message.toObject = function(includeInstance, msg) { + var f, obj = { + mid: jspb.Message.getFieldWithDefault(msg, 1, ""), + action: jspb.Message.getFieldWithDefault(msg, 2, ""), + content: jspb.Message.getFieldWithDefault(msg, 3, ""), + sender: jspb.Message.getFieldWithDefault(msg, 4, ""), + receiver: jspb.Message.getFieldWithDefault(msg, 5, ""), + extra: jspb.Message.getFieldWithDefault(msg, 6, ""), + title: jspb.Message.getFieldWithDefault(msg, 7, ""), + format: jspb.Message.getFieldWithDefault(msg, 8, ""), + timestamp: jspb.Message.getFieldWithDefault(msg, 9, 0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.com.farsunset.cim.sdk.web.model.Message} + */ +proto.com.farsunset.cim.sdk.web.model.Message.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.com.farsunset.cim.sdk.web.model.Message; + return proto.com.farsunset.cim.sdk.web.model.Message.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.com.farsunset.cim.sdk.web.model.Message} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.com.farsunset.cim.sdk.web.model.Message} + */ +proto.com.farsunset.cim.sdk.web.model.Message.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {string} */ (reader.readString()); + msg.setMid(value); + break; + case 2: + var value = /** @type {string} */ (reader.readString()); + msg.setAction(value); + break; + case 3: + var value = /** @type {string} */ (reader.readString()); + msg.setContent(value); + break; + case 4: + var value = /** @type {string} */ (reader.readString()); + msg.setSender(value); + break; + case 5: + var value = /** @type {string} */ (reader.readString()); + msg.setReceiver(value); + break; + case 6: + var value = /** @type {string} */ (reader.readString()); + msg.setExtra(value); + break; + case 7: + var value = /** @type {string} */ (reader.readString()); + msg.setTitle(value); + break; + case 8: + var value = /** @type {string} */ (reader.readString()); + msg.setFormat(value); + break; + case 9: + var value = /** @type {number} */ (reader.readInt64()); + msg.setTimestamp(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.com.farsunset.cim.sdk.web.model.Message.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.com.farsunset.cim.sdk.web.model.Message} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.com.farsunset.cim.sdk.web.model.Message.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getMid(); + if (f.length > 0) { + writer.writeString( + 1, + f + ); + } + f = message.getAction(); + if (f.length > 0) { + writer.writeString( + 2, + f + ); + } + f = message.getContent(); + if (f.length > 0) { + writer.writeString( + 3, + f + ); + } + f = message.getSender(); + if (f.length > 0) { + writer.writeString( + 4, + f + ); + } + f = message.getReceiver(); + if (f.length > 0) { + writer.writeString( + 5, + f + ); + } + f = message.getExtra(); + if (f.length > 0) { + writer.writeString( + 6, + f + ); + } + f = message.getTitle(); + if (f.length > 0) { + writer.writeString( + 7, + f + ); + } + f = message.getFormat(); + if (f.length > 0) { + writer.writeString( + 8, + f + ); + } + f = message.getTimestamp(); + if (f !== 0) { + writer.writeInt64( + 9, + f + ); + } +}; + + +/** + * optional string mid = 1; + * @return {string} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.getMid = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 1, "")); +}; + + +/** @param {string} value */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.setMid = function(value) { + jspb.Message.setProto3StringField(this, 1, value); +}; + + +/** + * optional string action = 2; + * @return {string} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.getAction = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 2, "")); +}; + + +/** @param {string} value */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.setAction = function(value) { + jspb.Message.setProto3StringField(this, 2, value); +}; + + +/** + * optional string content = 3; + * @return {string} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.getContent = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 3, "")); +}; + + +/** @param {string} value */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.setContent = function(value) { + jspb.Message.setProto3StringField(this, 3, value); +}; + + +/** + * optional string sender = 4; + * @return {string} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.getSender = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 4, "")); +}; + + +/** @param {string} value */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.setSender = function(value) { + jspb.Message.setProto3StringField(this, 4, value); +}; + + +/** + * optional string receiver = 5; + * @return {string} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.getReceiver = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 5, "")); +}; + + +/** @param {string} value */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.setReceiver = function(value) { + jspb.Message.setProto3StringField(this, 5, value); +}; + + +/** + * optional string extra = 6; + * @return {string} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.getExtra = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 6, "")); +}; + + +/** @param {string} value */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.setExtra = function(value) { + jspb.Message.setProto3StringField(this, 6, value); +}; + + +/** + * optional string title = 7; + * @return {string} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.getTitle = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 7, "")); +}; + + +/** @param {string} value */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.setTitle = function(value) { + jspb.Message.setProto3StringField(this, 7, value); +}; + + +/** + * optional string format = 8; + * @return {string} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.getFormat = function() { + return /** @type {string} */ (jspb.Message.getFieldWithDefault(this, 8, "")); +}; + + +/** @param {string} value */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.setFormat = function(value) { + jspb.Message.setProto3StringField(this, 8, value); +}; + + +/** + * optional int64 timestamp = 9; + * @return {number} + */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.getTimestamp = function() { + return /** @type {number} */ (jspb.Message.getFieldWithDefault(this, 9, 0)); +}; + + +/** @param {number} value */ +proto.com.farsunset.cim.sdk.web.model.Message.prototype.setTimestamp = function(value) { + jspb.Message.setProto3IntField(this, 9, value); +}; + + +goog.object.extend(exports, proto.com.farsunset.cim.sdk.web.model); + +},{"google-protobuf":3}],2:[function(require,module,exports){ +var messageProtobuf= require('./MessageProtobuf'); + + module.exports = { + DataProto: messageProtobuf + } +},{"./MessageProtobuf":1}],3:[function(require,module,exports){ +(function (global,Buffer){ +var $jscomp={scope:{},getGlobal:function(a){return"undefined"!=typeof window&&window===a?a:"undefined"!=typeof global?global:a}};$jscomp.global=$jscomp.getGlobal(this);$jscomp.initSymbol=function(){$jscomp.global.Symbol||($jscomp.global.Symbol=$jscomp.Symbol);$jscomp.initSymbol=function(){}};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(a){return"jscomp_symbol_"+a+$jscomp.symbolCounter_++}; +$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();$jscomp.global.Symbol.iterator||($jscomp.global.Symbol.iterator=$jscomp.global.Symbol("iterator"));$jscomp.initSymbolIterator=function(){}};$jscomp.makeIterator=function(a){$jscomp.initSymbolIterator();$jscomp.initSymbol();$jscomp.initSymbolIterator();var b=a[Symbol.iterator];if(b)return b.call(a);var c=0;return{next:function(){return cb;)--c in this?this[--a]=this[c]:delete this[a];return this};$jscomp.array.copyWithin$install=function(){$jscomp.array.installHelper_("copyWithin",$jscomp.array.copyWithin)}; +$jscomp.array.fill=function(a,b,c){var d=this.length||0;0>b&&(b=Math.max(0,d+b));if(null==c||c>d)c=d;c=Number(c);0>c&&(c=Math.max(0,d+c));for(b=Number(b||0);b>>0;if(0===a)return 32;var b=0;0===(a&4294901760)&&(a<<=16,b+=16);0===(a&4278190080)&&(a<<=8,b+=8);0===(a&4026531840)&&(a<<=4,b+=4);0===(a&3221225472)&&(a<<=2,b+=2);0===(a&2147483648)&&b++;return b};$jscomp.math.imul=function(a,b){a=Number(a);b=Number(b);var c=a&65535,d=b&65535;return c*d+((a>>>16&65535)*d+c*(b>>>16&65535)<<16>>>0)|0};$jscomp.math.sign=function(a){a=Number(a);return 0===a||isNaN(a)?a:0a&&-.25a&&-.25a?-b:b};$jscomp.math.acosh=function(a){a=Number(a);return Math.log(a+Math.sqrt(a*a-1))};$jscomp.math.asinh=function(a){a=Number(a);if(0===a)return a;var b=Math.log(Math.abs(a)+Math.sqrt(a*a+1));return 0>a?-b:b}; +$jscomp.math.atanh=function(a){a=Number(a);return($jscomp.math.log1p(a)-$jscomp.math.log1p(-a))/2};$jscomp.math.hypot=function(a,b,c){a=Number(a);b=Number(b);var d,e,f,g=Math.max(Math.abs(a),Math.abs(b));for(d=2;dg){a/=g;b/=g;f=a*a+b*b;for(d=2;da?-b:b};$jscomp.math.cbrt=function(a){if(0===a)return a;a=Number(a);var b=Math.pow(Math.abs(a),1/3);return 0>a?-b:b};$jscomp.number=$jscomp.number||{};$jscomp.number.isFinite=function(a){return"number"!==typeof a?!1:!isNaN(a)&&Infinity!==a&&-Infinity!==a};$jscomp.number.isInteger=function(a){return $jscomp.number.isFinite(a)?a===Math.floor(a):!1}; +$jscomp.number.isNaN=function(a){return"number"===typeof a&&isNaN(a)};$jscomp.number.isSafeInteger=function(a){return $jscomp.number.isInteger(a)&&Math.abs(a)<=$jscomp.number.MAX_SAFE_INTEGER};$jscomp.number.EPSILON=function(){return Math.pow(2,-52)}();$jscomp.number.MAX_SAFE_INTEGER=function(){return 9007199254740991}();$jscomp.number.MIN_SAFE_INTEGER=function(){return-9007199254740991}();$jscomp.object=$jscomp.object||{}; +$jscomp.object.assign=function(a,b){for(var c=1;cd||1114111=d?b+=String.fromCharCode(d):(d-=65536,b+=String.fromCharCode(d>>>10&1023|55296),b+=String.fromCharCode(d&1023|56320))}return b}; +$jscomp.string.repeat=function(a){var b=$jscomp.checkStringArgs(this,null,"repeat");if(0>a||1342177279>>=1)b+=b;return c};$jscomp.string.repeat$install=function(){String.prototype.repeat||(String.prototype.repeat=$jscomp.string.repeat)}; +$jscomp.string.codePointAt=function(a){var b=$jscomp.checkStringArgs(this,null,"codePointAt"),c=b.length;a=Number(a)||0;if(0<=a&&ad||56319a||57343=e}; +$jscomp.string.startsWith$install=function(){String.prototype.startsWith||(String.prototype.startsWith=$jscomp.string.startsWith)};$jscomp.string.endsWith=function(a,b){var c=$jscomp.checkStringArgs(this,a,"endsWith");a+="";void 0===b&&(b=c.length);for(var d=Math.max(0,Math.min(b|0,c.length)),e=a.length;0=e};$jscomp.string.endsWith$install=function(){String.prototype.endsWith||(String.prototype.endsWith=$jscomp.string.endsWith)}; +var COMPILED=!0,goog=goog||{};goog.global=this;goog.isDef=function(a){return void 0!==a};goog.exportPath_=function(a,b,c){a=a.split(".");c=c||goog.global;a[0]in c||!c.execScript||c.execScript("var "+a[0]);for(var d;a.length&&(d=a.shift());)!a.length&&goog.isDef(b)?c[d]=b:c=c[d]?c[d]:c[d]={}}; +goog.define=function(a,b){var c=b;COMPILED||(goog.global.CLOSURE_UNCOMPILED_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_UNCOMPILED_DEFINES,a)?c=goog.global.CLOSURE_UNCOMPILED_DEFINES[a]:goog.global.CLOSURE_DEFINES&&Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES,a)&&(c=goog.global.CLOSURE_DEFINES[a]));goog.exportPath_(a,c)};goog.DEBUG=!0;goog.LOCALE="en";goog.TRUSTED_SITE=!0;goog.STRICT_MODE_COMPATIBLE=!1;goog.DISALLOW_TEST_ONLY_CODE=COMPILED&&!goog.DEBUG; +goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING=!1;goog.provide=function(a){if(!COMPILED&&goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');goog.constructNamespace_(a)};goog.constructNamespace_=function(a,b){if(!COMPILED){delete goog.implicitNamespaces_[a];for(var c=a;(c=c.substring(0,c.lastIndexOf(".")))&&!goog.getObjectByName(c);)goog.implicitNamespaces_[c]=!0}goog.exportPath_(a,b)};goog.VALID_MODULE_RE_=/^[a-zA-Z_$][a-zA-Z0-9._$]*$/; +goog.module=function(a){if(!goog.isString(a)||!a||-1==a.search(goog.VALID_MODULE_RE_))throw Error("Invalid module identifier");if(!goog.isInModuleLoader_())throw Error("Module "+a+" has been loaded incorrectly.");if(goog.moduleLoaderState_.moduleName)throw Error("goog.module may only be called once per module.");goog.moduleLoaderState_.moduleName=a;if(!COMPILED){if(goog.isProvided_(a))throw Error('Namespace "'+a+'" already declared.');delete goog.implicitNamespaces_[a]}};goog.module.get=function(a){return goog.module.getInternal_(a)}; +goog.module.getInternal_=function(a){if(!COMPILED)return goog.isProvided_(a)?a in goog.loadedModules_?goog.loadedModules_[a]:goog.getObjectByName(a):null};goog.moduleLoaderState_=null;goog.isInModuleLoader_=function(){return null!=goog.moduleLoaderState_}; +goog.module.declareLegacyNamespace=function(){if(!COMPILED&&!goog.isInModuleLoader_())throw Error("goog.module.declareLegacyNamespace must be called from within a goog.module");if(!COMPILED&&!goog.moduleLoaderState_.moduleName)throw Error("goog.module must be called prior to goog.module.declareLegacyNamespace.");goog.moduleLoaderState_.declareLegacyNamespace=!0}; +goog.setTestOnly=function(a){if(goog.DISALLOW_TEST_ONLY_CODE)throw a=a||"",Error("Importing test-only code into non-debug environment"+(a?": "+a:"."));};goog.forwardDeclare=function(a){};COMPILED||(goog.isProvided_=function(a){return a in goog.loadedModules_||!goog.implicitNamespaces_[a]&&goog.isDefAndNotNull(goog.getObjectByName(a))},goog.implicitNamespaces_={"goog.module":!0}); +goog.getObjectByName=function(a,b){for(var c=a.split("."),d=b||goog.global,e;e=c.shift();)if(goog.isDefAndNotNull(d[e]))d=d[e];else return null;return d};goog.globalize=function(a,b){var c=b||goog.global,d;for(d in a)c[d]=a[d]};goog.addDependency=function(a,b,c,d){if(goog.DEPENDENCIES_ENABLED){var e;a=a.replace(/\\/g,"/");for(var f=goog.dependencies_,g=0;e=b[g];g++)f.nameToPath[e]=a,f.pathIsModule[a]=!!d;for(d=0;b=c[d];d++)a in f.requires||(f.requires[a]={}),f.requires[a][b]=!0}}; +goog.ENABLE_DEBUG_LOADER=!0;goog.logToConsole_=function(a){goog.global.console&&goog.global.console.error(a)};goog.require=function(a){if(!COMPILED){goog.ENABLE_DEBUG_LOADER&&goog.IS_OLD_IE_&&goog.maybeProcessDeferredDep_(a);if(goog.isProvided_(a))return goog.isInModuleLoader_()?goog.module.getInternal_(a):null;if(goog.ENABLE_DEBUG_LOADER){var b=goog.getPathFromDeps_(a);if(b)return goog.writeScripts_(b),null}a="goog.require could not find: "+a;goog.logToConsole_(a);throw Error(a);}}; +goog.basePath="";goog.nullFunction=function(){};goog.abstractMethod=function(){throw Error("unimplemented abstract method");};goog.addSingletonGetter=function(a){a.getInstance=function(){if(a.instance_)return a.instance_;goog.DEBUG&&(goog.instantiatedSingletons_[goog.instantiatedSingletons_.length]=a);return a.instance_=new a}};goog.instantiatedSingletons_=[];goog.LOAD_MODULE_USING_EVAL=!0;goog.SEAL_MODULE_EXPORTS=goog.DEBUG;goog.loadedModules_={};goog.DEPENDENCIES_ENABLED=!COMPILED&&goog.ENABLE_DEBUG_LOADER; +goog.DEPENDENCIES_ENABLED&&(goog.dependencies_={pathIsModule:{},nameToPath:{},requires:{},visited:{},written:{},deferred:{}},goog.inHtmlDocument_=function(){var a=goog.global.document;return null!=a&&"write"in a},goog.findBasePath_=function(){if(goog.isDef(goog.global.CLOSURE_BASE_PATH))goog.basePath=goog.global.CLOSURE_BASE_PATH;else if(goog.inHtmlDocument_())for(var a=goog.global.document.getElementsByTagName("SCRIPT"),b=a.length-1;0<=b;--b){var c=a[b].src,d=c.lastIndexOf("?"),d=-1==d?c.length: +d;if("base.js"==c.substr(d-7,7)){goog.basePath=c.substr(0,d-7);break}}},goog.importScript_=function(a,b){(goog.global.CLOSURE_IMPORT_SCRIPT||goog.writeScriptTag_)(a,b)&&(goog.dependencies_.written[a]=!0)},goog.IS_OLD_IE_=!(goog.global.atob||!goog.global.document||!goog.global.document.all),goog.importModule_=function(a){goog.importScript_("",'goog.retrieveAndExecModule_("'+a+'");')&&(goog.dependencies_.written[a]=!0)},goog.queuedModules_=[],goog.wrapModule_=function(a,b){return goog.LOAD_MODULE_USING_EVAL&& +goog.isDef(goog.global.JSON)?"goog.loadModule("+goog.global.JSON.stringify(b+"\n//# sourceURL="+a+"\n")+");":'goog.loadModule(function(exports) {"use strict";'+b+"\n;return exports});\n//# sourceURL="+a+"\n"},goog.loadQueuedModules_=function(){var a=goog.queuedModules_.length;if(0\x3c/script>')},goog.appendScriptSrcNode_=function(a){var b=goog.global.document, +c=b.createElement("script");c.type="text/javascript";c.src=a;c.defer=!1;c.async=!1;b.head.appendChild(c)},goog.writeScriptTag_=function(a,b){if(goog.inHtmlDocument_()){var c=goog.global.document;if(!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING&&"complete"==c.readyState){if(/\bdeps.js$/.test(a))return!1;throw Error('Cannot write "'+a+'" after document load');}var d=goog.IS_OLD_IE_;void 0===b?d?(d=" onreadystatechange='goog.onScriptLoad_(this, "+ ++goog.lastNonModuleScriptIndex_+")' ",c.write('