This commit is contained in:
lightings 2023-04-12 14:37:56 +08:00
parent 4b1bb8d079
commit 3620fdae36
26 changed files with 3628 additions and 3 deletions

View File

@ -124,7 +124,7 @@ public class LoginGUI : MonoBehaviour {
public void Login()
{
string host = "127.0.0.1";
string host = "bee.local";
int port = 3999;
// if (pc != null)
// {

856
docs/cs_friend_proto.proto Normal file
View File

@ -0,0 +1,856 @@
package cs;
//
enum Constant_e
{
ProtoVersion = 2020061101; //
}
//(60)
message CMPing
{
}
message SMPing
{
optional int32 param1 = 1;
}
//string元组
message MFStringTuple
{
repeated string values = 1; //values
}
//int32 pair
message MFPairInt32
{
optional int32 key = 1; //key
optional int32 val = 2; //val
}
//int64 pair
message MFPairInt64
{
optional int64 key = 1; //key
optional int64 val = 2; //val
}
//
message MFPaging
{
optional int32 curr_page = 1; //0
optional int32 page_size = 2; //
optional int32 _total_page = 3; //
optional int32 _total_count = 4; //
}
//(线db)
message MFBaseUserData
{
optional string account_id = 1; //id
optional string nickname = 2; //
optional string avatar_url = 3; //
optional int32 sex = 4; // 1 2 0
optional int32 last_login_time = 5; //
optional int64 guild_id = 6; //id(0)
optional int32 guild_job = 7; // 1: 2: 3 (0)
optional int32 vip_lv = 8 [default = 0]; //
optional int32 head = 9 [default = 0]; //
optional int32 contribute = 10 [default = 0]; //
optional int64 user_value1 = 50; //1
optional int64 user_value2 = 51; //2
optional int64 user_value3 = 52; //3
optional int64 base_data_version = 100; //
optional int32 _online = 101; //线
}
//(/线0)
message MFUserTempCustomData
{
optional int64 value1 = 1 [default = 0]; //1
optional int64 value2 = 2 [default = 0]; //2
optional int64 value3 = 3 [default = 0]; //3
}
//()
message MFAccountInfo
{
optional MFUserInfo user_info = 1; //
optional string user_sign = 2; //
}
//
message MFUserInfo
{
optional MFBaseUserData base_data = 1; //
optional MFUserTempCustomData temp_custom_data = 2; //
optional int32 is_sys_user = 3; //
}
//
message MFUserStatus
{
optional string account_id = 1; //id
optional int32 _online = 2; //线
optional MFUserTempCustomData temp_custom_data = 3; //
}
//
message MFFriendApply
{
optional int64 idx = 1; //id
optional int64 applyid = 2; //applyid
optional string target_id = 3; //target_id
optional MFBaseUserData base_data = 4; //
}
//
message MFGuildApply
{
optional int64 idx = 1; //id
optional int64 applyid = 2; //applyid
optional int64 guild_id = 3; //guild_id
optional MFBaseUserData base_data = 4; //
}
//
message MFGuildBasic
{
optional int64 guild_id = 1; //id
optional string guild_name = 2; //
optional int32 guild_lv = 3; //
optional double guild_exp = 4; //
optional int32 guild_badge = 5; //
optional int32 member_num = 6; //
optional string guild_declaration = 7; //
optional string owner_id = 8; //id
optional string owner_name = 9; //
optional string owner_avatar_url = 10; //
optional int32 owner_sex = 23; //
optional int32 owner_vip_lv = 12 [default = 0]; //vip等级
optional int32 owner_head = 13 [default = 0]; //
optional int32 join_unlimited = 11; //
optional int32 join_cond1 = 20; //1
optional int32 join_cond2 = 21; //2
optional int32 applyed = 22; //
optional int32 _gameid = 100; //gameid
optional int32 _channel = 101; //channel
optional int32 _createtime = 102; //createtime
optional int32 _modifytime = 103; //modifytime
optional int64 _name_ext1 = 104; //name_ext1
optional int64 _name_ext2 = 105; //name_ext2
optional int64 _guild_status = 106; //guild_status
}
//
message MFChatMsg
{
/*
id,chat_channel + msg_uuid作为主键
!!!msg_uuid可能重复
*/
optional int64 msg_uuid = 1;
optional MFUserInfo sender = 2; //
optional MFUserInfo receiver = 3; //
optional int32 chat_channel = 4; //
optional int32 msg_type = 5; // 0(json) 1 (json) 2:()
optional string msg_body = 6; //(json类型里的字段!)
optional int32 send_time = 7; //
}
//
message CMLoginCommonHead
{
optional int32 server_id = 1; //
}
message CMLoginOld
{
optional string account_id = 3; //id
optional string session_id = 20; //sessionid
optional string nickname = 4; //
optional string avatar_url = 5; //
optional int32 sex = 6; //
}
message CMLogin
{
optional int32 server_id = 1; //(1)
optional string reserved2 = 2; //
optional string account_id = 3; //id
optional string session_id = 20; //sessionid
optional string nickname = 4; //
optional int32 proto_version = 5; //Constant_e.ProtoVersion
optional int32 sex = 6; //
optional string avatar_url = 7; //
optional int32 vip_lv = 8; //
optional int32 head = 9; //
}
//
message SMLogin
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
optional MFAccountInfo account_info = 3; //
}
//()
message CMUpdateUserInfo
{
optional string nickname = 2; //
optional string avatar_url = 3; //
optional int32 sex = 4; // 1 2 0
optional int32 vip_lv = 8; //
optional int32 head = 9; //
optional int32 contribute = 10; //
optional int64 user_value1 = 50; //1
optional int64 user_value2 = 51; //2
optional int64 user_value3 = 52; //3
optional int32 delay_time = 100; //()
optional int32 delay_flag = 101; //(1-16)flag定时器覆盖
}
//
message CMDirtyWordCheck
{
optional string text = 2; //
}
//
message SMDirtyWordCheck
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMGetUserGuild
{
optional string account_id = 1; //id
}
//
message SMGetUserGuild
{
optional int32 errcode = 1; //1:
optional string errmsg = 2; //
optional string account_id = 3; //id
optional int64 guild_id = 4; //id(0)
optional int32 guild_job = 5; // 1: 2: 3 (0)
}
//
message CMFriendList
{
}
//
message SMFriendList
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
repeated MFUserInfo friend_list = 3; //
}
//
message CMFriendApply
{
optional string friend_id = 1; //id
optional string msg = 2; //
}
//
message SMFriendApply
{
optional int32 errcode = 1; //1:
optional string errmsg = 2; //
}
//
message CMFriendApplyList
{
optional MFPaging paging = 1; //
}
//
message SMFriendApplyList
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
optional MFPaging paging = 3; //
repeated MFFriendApply apply_list = 4; //
}
//
message CMFriendAgree
{
optional MFFriendApply apply = 1; //
}
//
message SMFriendAgree
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMFriendRefuse
{
optional MFFriendApply apply = 1; //
}
//
message SMFriendRefuse
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMFriendDelete
{
optional string friend_id = 1; //id
}
//
message SMFriendDelete
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
optional string friend_id = 3; //id
}
//
message CMFriendBlackList
{
}
//
message SMFriendBlackList
{
repeated MFUserInfo black_list = 1; //
}
//
message CMFriendAddBlack
{
optional MFUserInfo user_info = 1; //
}
//
message SMFriendAddBlack
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMFriendDeleteBlack
{
optional string account_id = 1; //id
}
//
message SMFriendDeleteBlack
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
///id列表
message CMFriendIdList
{
}
///id列表回复
message SMFriendIdList
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
repeated string friends = 3; //
repeated string blacklist = 4; //
}
//
message CMTeamCreate
{
optional string team_name = 1; //
}
//
message SMTeamCreate
{
optional int32 errcode = 1; //1: 2:
optional string errmsg = 2; //
}
//
message CMTeamJoin
{
optional int64 team_id = 1; //id
}
//
message SMTeamJoin
{
optional int32 errcode = 1; //1:id不存在 2:
optional string errmsg = 2; //
}
//
message CMTeamAgree
{
}
message SMTeamAgree
{
optional int32 errcode = 1;
optional string errmsg = 2;
}
//
message CMTeamKick
{
optional string account_id = 1;
}
//
message SMTeamKick
{
optional int32 errcode = 1; //1:id错误
optional string errmsg = 2; //
}
//退
message CMTeamQuit
{
}
message SMTeamQuit
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMTeamDismiss
{
}
message SMTeamDismiss
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMTeamRename
{
optional string new_team_name = 1; //
}
message SMTeamRename
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMGuildInfo
{
optional int64 guild_id = 1; //id
}
//
message SMGuildInfo
{
optional int32 errcode = 1; //1:
optional string errmsg = 2; //
optional MFGuildBasic info = 3; //
}
//
message CMGuildCreate
{
optional string guild_name = 1; //
optional int32 guild_badge = 2; //
optional string guild_declaration = 3; //
optional int32 join_unlimited = 4; //
optional int32 join_cond1 = 5; //1
optional int32 join_cond2 = 6; //2
}
//
message SMGuildCreate
{
optional int32 errcode = 1; //1: 2:
optional string errmsg = 2; //
optional int64 guild_id = 3; //id
}
//
message CMGuildJoin
{
optional int64 guild_id = 1; //id
}
//
message SMGuildJoin
{
optional int32 errcode = 1; //1:id不存在 2:
optional string errmsg = 2; //
}
//
message CMGuildAgree
{
optional MFGuildApply apply = 1; //
optional int32 batchid = 2; //id相同建议用时间戳
}
message SMGuildAgree
{
optional int32 errcode = 1;
optional string errmsg = 2;
}
//
message CMGuildRefuse
{
optional MFGuildApply apply = 1; //
optional int32 batchid = 2; //id相同建议用时间戳
}
message SMGuildRefuse
{
optional int32 errcode = 1;
optional string errmsg = 2;
}
//
message CMGuildKick
{
optional string account_id = 1;
}
//
message SMGuildKick
{
optional int32 errcode = 1; //1:id错误
optional string errmsg = 2; //
}
//退
message CMGuildQuit
{
}
message SMGuildQuit
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMGuildDismiss
{
}
message SMGuildDismiss
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//()
message CMGuildChange
{
optional string guild_name = 1; //
optional int32 guild_badge = 2; //
optional string guild_declaration = 3; //
optional int32 join_unlimited = 4; //
optional int32 join_cond1 = 5; //1
optional int32 join_cond2 = 6; //2
}
message SMGuildChange
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
optional MFGuildBasic info = 3; //
}
//
message CMGuildSearch
{
optional MFPaging paging = 1; //
optional string guild_name = 2; //
}
message SMGuildSearch
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
optional MFPaging paging = 3; //
repeated MFGuildBasic guild_list = 4; //
}
//
message CMGuildRank
{
optional MFPaging paging = 1; //
}
message SMGuildRank
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
optional MFPaging paging = 3; //
repeated MFGuildBasic guild_list = 4; //
}
//
message CMGuildMemberList
{
optional MFPaging paging = 1; //
optional string member_name = 2; //
}
message SMGuildMemberList
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
optional MFPaging paging = 3; //
repeated MFUserInfo member_list = 4; //
optional int32 guild_lv = 5; //
}
//
message CMGuildApplyList
{
optional MFPaging paging = 1; //
}
//
message SMGuildApplyList
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
optional MFPaging paging = 3; //
repeated MFGuildApply apply_list = 4; //
optional int32 guild_lv = 5; //
}
//()
message CMGuildLog
{
optional MFPaging paging = 1; //
}
message SMGuildLog
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
optional MFPaging paging = 3; //
/*
values[0]: account_id
values[1]:
values[2]: 1: 2: 3: (0):
values[3]: (unix时间戳)
values[4]:
*/
repeated MFStringTuple logs = 4;
}
//
message CMGuildMemberSetJob
{
optional string member_id = 1; //id
optional int32 job = 2; //
}
message SMGuildMemberSetJob
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMGuildAgreeInvite
{
optional int64 guild_id = 1; //id
optional string user_sign = 2; //
}
message SMGuildAgreeInvite
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMGuildGainExp
{
optional int32 exp = 1; //
}
message SMGuildGainExp
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
}
//
message CMGuildSearchMember
{
optional string target_id = 1; //id
}
message SMGuildSearchMember
{
optional int32 errcode = 1; //
optional string errmsg = 2; //
optional MFGuildBasic guild_basic = 3; //
optional MFUserInfo user_info = 4; //
}
//
message CMSendChatMsg
{
optional int32 chat_channel = 1; // 1: 2 3 4:target表示队伍Id 5 6
optional string target = 2; //
optional int32 msg_type = 3; //// 0(json) 1 (json) 2:()
optional string msg_body = 4; //
repeated string members = 5; //()
}
//
message CMReadMsgAndOpenChatNotify
{
optional int32 curr_channel = 1; //
repeated MFPairInt64 last_ids = 2; // key valid
}
//
message CMSetCurrPrivateChatTarget
{
optional string private_target = 1; //id,
optional int64 last_id = 2; //id
}
//
message CMCloseChatNotify
{
}
//
message CMSendCustomMsg
{
repeated string target_list = 1; //
optional string msg = 2; //
optional int64 param1 = 3; //1
optional int64 param2 = 4; //2
optional int64 param3 = 5; //3
}
//
message CMUpdateTempCustomData
{
/*
0:
1:
2:
!!!
MFUserRaltimeData走的是增量更新如果不需要处理的字段不传就行
*/
optional int32 update_type = 1; //
optional MFUserTempCustomData temp_custom_data = 2; //
optional int32 delay_time = 100; //()
optional int32 delay_flag = 101; //(1-16)flag定时器覆盖
}
//
message CMQueryUserStatus
{
repeated string user_list = 1; //
}
//
message SMQueryUserStatus
{
repeated MFUserStatus status_list = 1; //
}
//
message CMRecommandFriend
{
}
//
message SMRecommandFriend
{
repeated MFUserInfo friend_list = 1; //
}
///线
message SMUserStatusNotify
{
repeated string online_users = 1; //线
repeated string offline_users = 2; //线
}
//
message SMChatMsgNotify
{
repeated MFChatMsg msg_list = 1; //chat_channel和msg_uuid更新本地的last_ids
}
//
message SMCustomMsgNotify
{
optional string sender = 1; //
optional string msg = 2; //
optional int64 param1 = 3; //1
optional int64 param2 = 4; //2
optional int64 param3 = 5; //3
}
//
message SMUserInfoUpdate
{
repeated MFUserInfo user_infos = 1; //
}
//a
message SMDeleteFriendNotify
{
repeated string user_list = 1; //
}
//
message SMAddBlackListNotify
{
repeated MFUserInfo user_infos = 1; //
}
//
message SMDeleteBlackListNotify
{
repeated string user_list = 1; //
}
//
message SMUserTempCustomDataUpdate
{
optional string account_id = 1; //id
optional MFUserTempCustomData temp_custom_data = 2; //
}
//
message SMUpdateAccountInfo
{
}
//
message SMUpdateRedPointNotify
{
optional int32 red_point_flags = 1; // 1<<0: 1<<1: 1<<2
}
//
message SMUpdateChatRedPointNotify
{
repeated int32 has_unread_msg_channels = 1; //id列表
}
//
message SMUpdatePrivateChatRedPointNotify
{
repeated string has_unread_msg_accounts = 1; //more不含有
}
//id
message SMUpdateChatChannelLastId
{
repeated MFPairInt64 last_ids = 1; // key valid
}
//
message SMShowErrorMsg
{
optional string msg = 1; //
}

View File

@ -1,8 +1,8 @@
{
"development":{
"connector": [
{"id": "connector-server-0", "host": "127.0.0.1", "port": 3150, "clientHost": "0.0.0.0", "proxyHost": "localhost", "clientPort": 3010, "frontend": true},
{"id": "connector-server-1", "host": "127.0.0.1", "port": 3151, "clientHost": "0.0.0.0", "proxyHost": "localhost", "clientPort": 3011, "frontend": true}
{"id": "connector-server-0", "host": "127.0.0.1", "port": 3150, "clientHost": "0.0.0.0", "proxyHost": "192.168.100.173", "clientPort": 4010, "frontend": true},
{"id": "connector-server-1", "host": "127.0.0.1", "port": 3151, "clientHost": "0.0.0.0", "proxyHost": "192.168.100.173", "clientPort": 4011, "frontend": true}
],
"guild": [
{"id": "guild-server-0", "host": "127.0.0.1", "port": 3200},

17
proxy/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,17 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/app.js"
}
]
}

108
proxy/app.js Normal file
View File

@ -0,0 +1,108 @@
const net = require("net");
const { PomeloClient } = require("./lib/boot");
var listenPort = 4000;
var listenHost = "127.0.0.1";
const proxyList = require("./config/proxy.json");
console.log(proxyList);
proxyList.forEach((config) => {
proxy(config);
});
function proxy(config) {
console.log(config);
const host = config.host;
const port = config.port;
const srcHost = config.srcHost;
const srcPort = config.srcPort;
const server = net.createServer((socket) => {
console.log("listening");
const pomelo = new PomeloClient();
const connectBuffer = [];
let isReady = false;
pomelo.init({ host: srcHost, port: srcPort, log: true }, () => {
isReady = true;
connectBuffer.forEach((data) => {
onData(data);
});
}
);
socket.on("connect", () => {
console.log("connect");
});
socket.on("error", (error) => {
console.log(error);
});
socket.on("close", () => {
console.log("close");
pomelo.disconnect();
});
socket.on("drop", () => {
console.log("drop");
});
socket.on("data", (data) => {
if (isReady) {
onData(data);
} else {
connectBuffer.push(data);
}
});
function onData(data) {
console.log(data.toString());
const account = "6516_2006_0xef59f6cc4d190a0ae576c46d4583e92b61174340";
pomelo.request("gate.gateHandler.queryEntry", { uid: account }, (data) => {
socket.write(JSON.stringify(data));
});
}
});
server.listen(port, host);
}
// const testAccounts = [
// "6516_2006_0xef59f6cc4d190a0ae576c46d4583e92b61174340",
// "6513_2006_FcZnmeGSoxGFQy1Zr6Lfr2o7dRoGcEYE",
// "6513_2006_DAmSOj6LKh1jd45DlydwUm7g8iW4KjOv",
// ];
// testAccounts.forEach((account) => {
// const pomelo = new PomeloClient();
// pomelo.init(
// {
// host: "192.168.100.173",
// port: 3999,
// log: true,
// },
// () => {
// pomelo.request(
// "gate.gateHandler.queryEntry",
// { uid: account },
// (data) => {
// console.log(data);
// }
// );
// }
// );
// });

33
proxy/client.js Normal file
View File

@ -0,0 +1,33 @@
const net = require("net");
const port = 4999;
const host = "127.0.0.1";
var client = new net.Socket();
client.connect(port, host, function () {
console.log("Connected");
client.write("queryEntry");
});
client.on("data", function (data) {
data = JSON.parse(data);
console.log("Received: " + data);
client.destroy(); // kill client after server's response
const game = new net.Socket();
console.log(data.port, data.host);
game.connect(data.port, data.host, function () {
console.log("Connected");
game.write("entry");
});
});
client.on("error", function (error) {
console.log("Error: " + error);
});
client.on("close", function () {
console.log("Connection closed");
});

5
proxy/config/proxy.json Normal file
View File

@ -0,0 +1,5 @@
[
{ "host": "127.0.0.1", "port": 4999, "srcHost":"192.168.100.173", "srcPort": 3999 },
{ "host": "127.0.0.1", "port": 4010, "srcHost":"192.168.100.173", "srcPort": 3010 },
{ "host": "127.0.0.1", "port": 4011, "srcHost":"192.168.100.173", "srcPort": 3011 }
]

6
proxy/lib/boot.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
EventEmitter: require('./deps/emitter'),
Protocol: require('./deps/pomelo-protocol'),
protobuf: require('./deps/pomelo-protobuf'),
PomeloClient: require('./deps/pomelo-jsclient'),
}

157
proxy/lib/deps/emitter.js Normal file
View File

@ -0,0 +1,157 @@
var index = require('./indexof');
/**
* 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 = 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);
}
fn._off = on;
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 = 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 i = index(callbacks, fn._off || fn);
if (~i) callbacks.splice(i, 1);
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;
};

View File

@ -0,0 +1,9 @@
var indexOf = [].indexOf;
module.exports = function(arr, obj){
if (indexOf) return arr.indexOf(obj);
for (var i = 0; i < arr.length; ++i) {
if (arr[i] === obj) return i;
}
return -1;
};

View File

@ -0,0 +1,337 @@
const net = require("net");
var JS_WS_CLIENT_TYPE = "js-websocket";
var JS_WS_CLIENT_VERSION = "0.0.1";
var Protocol = require("./pomelo-protocol");
var Package = Protocol.Package;
var Message = Protocol.Message;
var EventEmitter = require("./emitter");
const protobuf = require("./pomelo-protobuf");
var RES_OK = 200;
var RES_FAIL = 500;
var RES_OLD_CLIENT = 501;
class PomeloClient extends EventEmitter {
constructor() {
super();
this.socket = null;
this.reqId = 0;
this.callbacks = {};
this.handlers = {};
//Map from request id to route
this.routeMap = {};
this.heartbeatInterval = 0;
this.heartbeatTimeout = 0;
this.nextHeartbeatTimeout = 0;
this.gapThreshold = 100; // heartbeat gap threashold
this.heartbeatId = null;
this.heartbeatTimeoutId = null;
this.handshakeCallback = null;
this.handshakeBuffer = {
sys: {
type: JS_WS_CLIENT_TYPE,
version: JS_WS_CLIENT_VERSION,
},
user: {},
};
this.initCallback = null;
this.handlers[Package.TYPE_HANDSHAKE] = this.handshake.bind(this);
this.handlers[Package.TYPE_HEARTBEAT] = this.heartbeat.bind(this);
this.handlers[Package.TYPE_DATA] = this.onData.bind(this);
this.handlers[Package.TYPE_KICK] = this.onKick.bind(this);
}
init(params, cb) {
this.initCallback = cb;
var host = params.host;
var port = params.port;
this.handshakeBuffer.user = params.user;
this.handshakeCallback = params.handshakeCallback;
this.initWebSocket(host, port, cb);
}
disconnect() {
if (this.socket) {
if (this.socket.disconnect) this.socket.disconnect();
if (this.socket.close) this.socket.close();
console.log("disconnect");
this.socket = null;
}
if (this.heartbeatId) {
clearTimeout(this.heartbeatId);
this.heartbeatId = null;
}
if (this.heartbeatTimeoutId) {
clearTimeout(this.heartbeatTimeoutId);
this.heartbeatTimeoutId = null;
}
}
request(route, msg, cb) {
if (arguments.length === 2 && typeof msg === "function") {
cb = msg;
msg = {};
} else {
msg = msg || {};
}
route = route || msg.route;
if (!route) {
return;
}
this.reqId++;
this.sendMessage(this.reqId, route, msg);
this.callbacks[this.reqId] = cb;
this.routeMap[this.reqId] = route;
}
notify(route, msg) {
msg = msg || {};
this.sendMessage(0, route, msg);
}
sendMessage(reqId, route, msg) {
var type = reqId ? Message.TYPE_REQUEST : Message.TYPE_NOTIFY;
//compress message by protobuf
var protos = !!this.data.protos ? this.data.protos.client : {};
if (!!protos[route]) {
msg = protobuf.encode(route, msg);
} else {
msg = Protocol.strencode(JSON.stringify(msg));
}
var compressRoute = 0;
if (this.dict && this.dict[route]) {
route = this.dict[route];
compressRoute = 1;
}
msg = Message.encode(reqId, type, compressRoute, route, msg);
var packet = Package.encode(Package.TYPE_DATA, msg);
this.send(packet);
}
initWebSocket(host, port, cb) {
console.log("connect to " + host + ":" + port);
this.socket = net.connect(port, host, (event) => {
var obj = Package.encode(
Package.TYPE_HANDSHAKE,
Protocol.strencode(JSON.stringify(this.handshakeBuffer))
);
this.send(obj);
});
this.socket.on("data", (event) => {
this.processPackage(Package.decode(event), cb);
// new package arrived, update the heartbeat timeout
if (this.heartbeatTimeout) {
this.nextHeartbeatTimeout = Date.now() + this.heartbeatTimeout;
}
});
this.socket.on("error", (event) => {
this.emit("io-error", event);
console.error("socket error: ", event);
});
this.socket.on("close", (event) => {
this.emit("close", event);
console.error("socket close: ", event);
});
}
send(packet) {
this.socket.write(packet);
}
processPackage(msg) {
this.handlers[msg.type](msg.body);
}
heartbeat(data) {
if (!this.heartbeatInterval) {
// no heartbeat
return;
}
var obj = Package.encode(Package.TYPE_HEARTBEAT);
if (this.heartbeatTimeoutId) {
clearTimeout(this.heartbeatTimeoutId);
this.heartbeatTimeoutId = null;
}
if (this.heartbeatId) {
// already in a heartbeat interval
return;
}
this.heartbeatId = setTimeout(
function () {
this.heartbeatId = null;
this.send(obj);
this.nextHeartbeatTimeout = Date.now() + this.heartbeatTimeout;
this.heartbeatTimeoutId = setTimeout(
this.heartbeatTimeoutCb.bind(this),
this.heartbeatTimeout
);
}.bind(this),
this.heartbeatInterval
);
}
heartbeatTimeoutCb() {
var gap = this.nextHeartbeatTimeout - Date.now();
if (gap > this.gapThreshold) {
this.heartbeatTimeoutId = setTimeout(this.heartbeatTimeoutCb, gap);
} else {
console.error("server heartbeat timeout");
this.emit("heartbeat timeout");
this.disconnect();
}
}
handshake(data) {
data = JSON.parse(Protocol.strdecode(data));
if (data.code === RES_OLD_CLIENT) {
this.emit("error", "client version not fullfill");
return;
}
if (data.code !== RES_OK) {
this.emit("error", "handshake fail");
return;
}
this.handshakeInit(data);
var obj = Package.encode(Package.TYPE_HANDSHAKE_ACK);
this.send(obj);
if (this.initCallback) {
this.initCallback(this.socket);
this.initCallback = null;
}
}
handshakeInit(data) {
if (data.sys && data.sys.heartbeat) {
this.heartbeatInterval = data.sys.heartbeat * 1000; // heartbeat interval
this.heartbeatTimeout = this.heartbeatInterval * 2; // max heartbeat timeout
} else {
this.heartbeatInterval = 0;
this.heartbeatTimeout = 0;
}
this.initData(data);
if (typeof this.handshakeCallback === "function") {
this.handshakeCallback(data.user);
}
}
initData(data) {
if (!data || !data.sys) {
return;
}
this.data = this.data || {};
var dict = data.sys.dict;
var protos = data.sys.protos;
//Init compress dict
if (dict) {
this.data.dict = dict;
this.data.abbrs = {};
for (var route in dict) {
this.data.abbrs[dict[route]] = route;
}
}
//Init protobuf protos
if (protos) {
this.data.protos = {
server: protos.server || {},
client: protos.client || {},
};
if (!!protobuf) {
protobuf.init({
encoderProtos: protos.client,
decoderProtos: protos.server,
});
}
}
}
onData(data) {
//probuff decode
var msg = Message.decode(data);
if (msg.id > 0) {
msg.route = this.routeMap[msg.id];
delete this.routeMap[msg.id];
if (!msg.route) {
return;
}
}
msg.body = this.deCompose(msg);
this.processMessage(msg);
}
deCompose(msg) {
var protos = !!this.data.protos ? this.data.protos.server : {};
var abbrs = this.data.abbrs;
var route = msg.route;
//Decompose route from dict
if (msg.compressRoute) {
if (!abbrs[route]) {
return {};
}
route = msg.route = abbrs[route];
}
if (!!protos[route]) {
return protobuf.decode(route, msg.body);
} else {
return JSON.parse(Protocol.strdecode(msg.body));
}
return msg;
}
processMessage(msg) {
if(!msg.id) {
// server push message
this.emit(msg.route, msg.body);
return;
}
//if have a id then find the callback function with the request
var cb = this.callbacks[msg.id];
delete this.callbacks[msg.id];
if(typeof cb !== 'function') {
return;
}
cb(msg.body);
return;
};
onKick(data) {
this.emit("onKick");
}
}
module.exports = PomeloClient;

View File

@ -0,0 +1,611 @@
/* ProtocolBuffer client 0.1.0*/
/**
* pomelo-protobuf
* @author <zhang0935@gmail.com>
*/
/**
* Protocol buffer root
* In browser, it will be window.protbuf
*/
(function (exports, global){
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;
})('object' === typeof module ? module.exports : (this.protobuf = {}), this);
/**
* constants
*/
(function (exports, global){
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, this);
/**
* util module
*/
(function (exports, global){
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, this);
/**
* codec module
*/
(function (exports, global){
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 < (8 + offset)){
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, this);
/**
* encoder module
*/
(function (exports, global){
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(JSON.stringify(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'){
return false;
}
case 'optional' :
if(typeof(msg[name]) !== 'undefined'){
if(!!protos.__messages[proto.type]){
checkMsg(msg[name], protos.__messages[proto.type]);
}
}
break;
case 'repeated' :
//Check nest message in repeated elements
if(!!msg[name] && !!protos.__messages[proto.type]){
for(var i = 0; i < msg[name].length; i++){
if(!checkMsg(msg[name][i], protos.__messages[proto.type])){
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 :
if(!!protos.__messages[type]){
//Use a tmp buffer to build an internal msg
var tmpBuffer = new ArrayBuffer(codec.byteLength(JSON.stringify(value)));
var length = 0;
length = encodeMsg(tmpBuffer, length, protos.__messages[type], 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, this);
/**
* decoder module
*/
(function (exports, global){
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 :
if(!!protos && !!protos.__messages[type]){
var length = codec.decodeUInt32(getBytes());
var msg = {};
decodeMsg(msg, protos.__messages[type], 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, this);

View File

@ -0,0 +1,341 @@
const ByteArray = Uint8Array;
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);
}
var res = '';
var chunk = 8 * 1024;
var i;
for (i = 0; i < array.length / chunk; i++) {
res += String.fromCharCode.apply(null, array.slice(i * chunk, (i + 1) * chunk));
}
res += String.fromCharCode.apply(null, array.slice(i * chunk));
return res;
};
/**
* 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 bytes = new ByteArray(buffer);
var type = bytes[0];
var index = 1;
var length = ((bytes[index++]) << 16 | (bytes[index++]) << 8 | bytes[index++]) >>> 0;
var body = length ? new ByteArray(length) : null;
copyArray(body, 0, bytes, PKG_HEAD_BYTES, length);
return {'type': type, 'body': body};
};
/**
* 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, idBytes, 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 byte = bytes[offset++];
id = byte & 0x7f;
while(byte & 0x80) {
id <<= 7;
byte = bytes[offset++];
id |= byte & 0x7f;
}
}
// 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(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(type) {
return type === Message.TYPE_REQUEST || type === Message.TYPE_RESPONSE;
};
var msgHasRoute = function(type) {
return type === Message.TYPE_REQUEST || type === Message.TYPE_NOTIFY ||
type === Message.TYPE_PUSH;
};
var caculateMsgIdBytes = function(id) {
var len = 0;
do {
len += 1;
id >>= 7;
} while(id > 0);
return len;
};
var encodeMsgFlag = function(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(id, idBytes, buffer, offset) {
var index = offset + idBytes - 1;
buffer[index--] = id & 0x7f;
while(index >= offset) {
id >>= 7;
buffer[index--] = id & 0x7f | 0x80;
}
return offset + idBytes;
};
var encodeMsgRoute = function(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(msg, buffer, offset) {
copyArray(buffer, offset, msg, 0, msg.length);
return offset + msg.length;
};
module.exports = Protocol;

16
proxy/node_modules/.package-lock.json generated vendored Normal file
View File

@ -0,0 +1,16 @@
{
"name": "proxy",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"node_modules/bytearray": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/bytearray/-/bytearray-0.1.3.tgz",
"integrity": "sha512-oEKhhGYMfEdfnp4yViXVeauXLLYLj0hs8cQpJmu0JXbhuVX1iTeVmZ2IW4QtXhBcZitzOZ6pYNRvMDJRl5/0og==",
"engines": {
"node": ">= 0.8.0"
}
}
}
}

15
proxy/node_modules/bytearray/.jshintrc generated vendored Normal file
View File

@ -0,0 +1,15 @@
{
"curly": true,
"eqeqeq": true,
"immed": true,
"latedef": true,
"newcap": true,
"noarg": true,
"sub": true,
"undef": true,
"unused": true,
"boss": true,
"eqnull": true,
"node": true,
"es5": true
}

3
proxy/node_modules/bytearray/.npmignore generated vendored Normal file
View File

@ -0,0 +1,3 @@
/node_modules/
.DS_Store
*.swp

22
proxy/node_modules/bytearray/LICENSE-MIT generated vendored Normal file
View File

@ -0,0 +1,22 @@
Copyright (c) 2013 yi
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

31
proxy/node_modules/bytearray/README.md generated vendored Normal file
View File

@ -0,0 +1,31 @@
# bytearray
a Node.JS module for Buffer processing exposes API similar to ByteArray of ActionScript
## Install
Install the module with: `npm install bytearray`
```javascript
var bytearray = require('bytearray');
```
## Usage
* bytearray.readBoolean(buf, [offset]):Boolean
* bytearray.readInt(buf, [offset]):int
* bytearray.readShort(buf, [offset]):int
* bytearray.readUnsignedByte(buf, [offset]):uint
* bytearray.readUnsignedInt(buf, [offset]):uint
* bytearray.readUnsignedShort(buf, [offset]):uint
* bytearray.readUTF(buf, [offset]):String
* bytearray.readUTFByte(buf, [offset]s(length:uint):String
* bytearray.writeBoolean(value:Boolean):void
* bytearray.writeByte(value:int):void
* bytearray.writeBytes(bytes:ByteArray, offset:uint = 0, length:uint = 0):void
* bytearray.writeInt(value:int):void
* bytearray.writeShort(value:int):void
* bytearray.writeUnsignedInt(value:uint):void
* bytearray.writeUTF(value:String):void
## License
Copyright (c) 2013 yi
Licensed under the MIT license.

1
proxy/node_modules/bytearray/bin/coffee-watch.bat generated vendored Executable file
View File

@ -0,0 +1 @@
coffee -o ./lib/ -cw ./src/

367
proxy/node_modules/bytearray/lib/bytearray.js generated vendored Normal file
View File

@ -0,0 +1,367 @@
// Generated by CoffeeScript 1.6.3
/*
# a collection of utility methods for Buffer
#
# 这个工具类的设计以实现两个目地
# 1. 读写方法匹配 Actionscript ByteArray 读写方法
# 2. ActionScript 的默认采用 big endian这个工具方法对此进行封装以是外部不用关心 endian
#
*/
(function() {
module.exports = {
readUTF: function(buf, offset) {
var len;
if (!Buffer.isBuffer(buf)) {
return null;
}
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
if (buf.length <= offset + 2) {
return null;
}
len = buf.readUInt16BE(offset);
if (buf.length < len + offset) {
return null;
}
offset += 2;
buf.position = offset + len;
return buf.toString('utf8', offset, offset + len);
},
readUTFBytes: function(buf, length, offset) {
if (!Buffer.isBuffer(buf)) {
return null;
}
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
if (buf.length <= offset) {
return null;
}
buf.position = offset + length;
return buf.toString('utf8', offset, offset + length);
},
readFixLengthASCII: function(buf, offset) {
var len;
if (!Buffer.isBuffer(buf)) {
return null;
}
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
if (buf.length <= offset + 2) {
return null;
}
len = buf.readUInt8(offset);
if (buf.length < len + offset) {
return null;
}
offset += 1;
buf.position = offset + len;
return buf.toString('utf8', offset, offset + len);
},
readUnsignedShort: function(buf, offset) {
if (!Buffer.isBuffer(buf)) {
return 0;
}
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.position = offset + 2;
return buf.readUInt16BE(offset);
},
readShort: function(buf, offset) {
if (!Buffer.isBuffer(buf)) {
return 0;
}
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.position = offset + 2;
return buf.readInt16BE(offset);
},
readUnsignedByte: function(buf, offset) {
if (!Buffer.isBuffer(buf)) {
return 0;
}
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.position = offset + 1;
return buf.readUInt8(offset);
},
readByte: function(buf, offset) {
if (!Buffer.isBuffer(buf)) {
return 0;
}
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.position = offset + 1;
return buf.readInt8(offset);
},
readUnsignedInt: function(buf, offset) {
if (!Buffer.isBuffer(buf)) {
return 0;
}
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.position = offset + 4;
return buf.readUInt32BE(offset);
},
readInt: function(buf, offset) {
if (!Buffer.isBuffer(buf)) {
return 0;
}
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.position = offset + 4;
return buf.readInt32BE(offset);
},
readFloat: function(buf, offset) {
if (!Buffer.isBuffer(buf)) {
return 0;
}
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.position = offset + 4;
return buf.readFloatLE(offset);
},
readUnsignedIntArray: function(buf, offset) {
var a, arr, len;
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
len = buf.readUInt16BE(offset) >>> 2;
offset += 2;
arr = [];
if (len === 0 || len > 1024) {
buf.position = offset;
return arr;
}
while (len > 0) {
a = buf.readUInt32BE(offset);
arr.push(a);
offset += 4;
len -= 1;
}
buf.position = offset;
return arr;
},
writeUnsignedInt: function(buf, value, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.writeUInt32BE(value, offset);
buf.position = offset + 4;
},
writeInt: function(buf, value, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.writeInt32BE(value, offset);
buf.position = offset + 4;
},
writeFloat: function(buf, value, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.writeFloatLE(value, offset);
buf.position = offset + 4;
},
writeUnsignedShort: function(buf, value, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.writeUInt16BE(value, offset);
buf.position = offset + 2;
},
writeShort: function(buf, value, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.writeInt16BE(value, offset);
buf.position = offset + 2;
},
writeUnsignedByte: function(buf, value, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.writeUInt8(value, offset);
buf.position = offset + 1;
},
writeByte: function(buf, value, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.writeInt8(value, offset);
buf.position = offset + 1;
},
writeBoolean: function(buf, value, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
value = value ? 1 : 0;
buf.writeInt8(value, offset);
buf.position = offset + 1;
},
writeFixLengthASCII: function(buf, str, maxNumOfChar, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.writeUInt8(maxNumOfChar, offset);
offset += 1;
buf.fill(0x20, offset, offset + maxNumOfChar);
buf.write(str, offset, maxNumOfChar, 'ascii');
buf.position = offset + maxNumOfChar;
},
writeFixLengthUTF: function(buf, str, maxNumOfChar, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
maxNumOfChar *= 6;
buf.writeUInt16BE(maxNumOfChar, offset);
offset += 2;
buf.fill(0x20, offset, offset + maxNumOfChar);
buf.write(str, offset, maxNumOfChar, 'utf8');
buf.position = offset + maxNumOfChar;
},
writeUTF: function(buf, str, offset) {
var byteLength;
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
byteLength = Buffer.byteLength(str);
buf.writeUInt16BE(byteLength, offset);
offset += 2;
buf.write(str, offset);
buf.position = offset + byteLength;
},
writeUTFBytes: function(buf, str, offset) {
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
buf.write(str, offset);
buf.position = offset + Buffer.byteLength(str);
},
writeUTFArray: function(buf, strArray, offset) {
var byteLength, str, _i, _len;
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
if (!((strArray != null) && strArray.length > 0)) {
buf.writeUInt16BE(0, offset);
buf.position = offset + 2;
return;
}
buf.writeUInt16BE(strArray.length, offset);
offset += 2;
for (_i = 0, _len = strArray.length; _i < _len; _i++) {
str = strArray[_i];
byteLength = Buffer.byteLength(str);
buf.writeUInt16BE(byteLength, offset);
offset += 2;
buf.write(str, offset);
offset += byteLength;
}
return buf.position = offset;
},
getByteLengthOfUTFArray: function(strArray) {
var len, str, _i, _len;
len = 2;
if (!((strArray != null) && strArray.length > 0)) {
return len;
}
for (_i = 0, _len = strArray.length; _i < _len; _i++) {
str = strArray[_i];
len = len + 2 + Buffer.byteLength(str);
}
return len;
},
writeUnsignedIntArray: function(buf, arr, fixedLength, offset) {
var i, n, _i, _len;
if (fixedLength == null) {
fixedLength = -1;
}
arr = arr || [];
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
n = arr.length;
if (fixedLength > 0 && fixedLength !== n) {
if (fixedLength < n) {
arr = arr.slice(0, fixedLength);
} else {
arr = arr.concat();
arr.length = fixedLength;
}
n = fixedLength;
}
n = n << 2;
buf.writeUInt16BE(n, offset);
offset += 2;
for (_i = 0, _len = arr.length; _i < _len; _i++) {
i = arr[_i];
buf.writeUInt32BE(parseInt(i, 10) || 0, offset);
offset += 4;
}
buf.position = offset;
},
getByteLengthOfIntArray: function(arr) {
return (arr.length << 2) + 2;
},
writeUnsignedShortArray: function(buf, arr, fixedLength, offset) {
var i, n, _i, _len;
if (fixedLength == null) {
fixedLength = -1;
}
arr = arr || [];
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
n = arr.length;
if (fixedLength > 0 && fixedLength !== n) {
if (fixedLength < n) {
arr = arr.slice(0, fixedLength);
} else {
arr = arr.concat();
arr.length = fixedLength;
}
n = fixedLength;
}
n = n << 1;
buf.writeUInt16BE(n, offset);
offset += 2;
for (_i = 0, _len = arr.length; _i < _len; _i++) {
i = arr[_i];
buf.writeUInt16BE(parseInt(i, 10) || 0, offset);
offset += 2;
}
buf.position = offset;
},
getBytesAvailable: function(buf) {
if (buf != null) {
return buf.length - (buf.position || 0);
} else {
return 0;
}
},
scrap: function(buf, length) {
var offset, result;
if (!((buf != null) && length > 0)) {
return null;
}
offset = buf.position || 0;
if (length + offset > buf.length) {
return null;
}
result = new Buffer(length);
buf.copy(result, 0, offset, offset + length);
buf.position = offset + length;
return result;
},
duplicate: function(buf) {
var n, result;
n = buf.length || 0;
if (n === 0) {
return null;
}
result = new Buffer(n);
buf.copy(result, 0, 0, n);
return result;
},
utfStringToBuf: function(str) {
var buf, n;
str = String(str || '');
n = Buffer.byteLength(str, 'utf8');
buf = new Buffer(n + 2);
buf.writeUInt16BE(n, 0);
buf.write(str, 2);
return buf;
},
isAvailableBuf: function(buf) {
return Buffer.isBuffer(buf) && buf.length > 0;
},
writeIntArray: function(buf, arr, fixedLength, offset) {
var i, n, _i, _len;
if (fixedLength == null) {
fixedLength = -1;
}
arr = arr || [];
offset = offset < 0 ? buf.length + offset : (offset === 0 ? 0 : offset || buf.position || 0);
n = arr.length;
if (fixedLength > 0 && fixedLength !== n) {
if (fixedLength < n) {
arr = arr.slice(0, fixedLength);
} else {
arr = arr.concat();
arr.length = fixedLength;
}
n = fixedLength;
}
n = n << 2;
buf.writeUInt16BE(n, offset);
offset += 2;
for (_i = 0, _len = arr.length; _i < _len; _i++) {
i = arr[_i];
buf.writeInt32BE(parseInt(i, 10) || 0, offset);
offset += 4;
}
buf.position = offset;
}
};
}).call(this);

View File

@ -0,0 +1,92 @@
// Generated by CoffeeScript 1.6.3
(function() {
var FIXTURE_UTF, FIXTURE_UTF_BUFF, FIXTURE_UTF_BYTE_LENGTH, FIXTURE_UTF_LENGTH, UNIT_ARR, VECTOR_UINT_1, VECTOR_UINT_STR_1, bytearray, should;
require('mocha');
should = require('should');
bytearray = require('../byteArray');
FIXTURE_UTF = "这个LED花洒有意思@陈中 可建议 @吴海 在桔子酒店引入,";
FIXTURE_UTF_LENGTH = FIXTURE_UTF.length;
FIXTURE_UTF_BYTE_LENGTH = Buffer.byteLength(FIXTURE_UTF);
FIXTURE_UTF_BUFF = new Buffer(2 + FIXTURE_UTF_BYTE_LENGTH);
FIXTURE_UTF_BUFF.writeUInt16BE(FIXTURE_UTF_BYTE_LENGTH, 0);
FIXTURE_UTF_BUFF.write(FIXTURE_UTF, 2);
VECTOR_UINT_1 = [4196330, 4196812, 4198245, 4198550, 4196885, 4197941, 4197659, 4196640, 4196980, 4196368, 4196795, 4197527, 4196374, 4196672, 4197016, 4197661, 4197014, 4197449, 4197615, 4196330, 4196579, 4196714, 4196835, 4196808, 4196786, 4197947, 4196473, 4196646, 4197939, 4197928, 4196366, 4197926, 4197559, 4196333, 4198850, 4196840, 4197927, 4196511, 4197938, 4196812, 4197925, 4197526, 4196312, 4196804, 4197528, 4196682, 4196954, 4196409, 4196258, 4198177, 4196291, 4198245, 4198180, 4196216, 4198277, 4196263, 4198280, 4198276, 4198282, 4198201, 4198279, 4197004, 4198211, 4197011, 4196759, 4197097, 4196512, 4197018, 4198236, 4198304, 4196397, 4198237, 4198312, 4198198, 4198199, 4198259, 4198310, 4198305, 4197201, 4198160, 4198326, 4198189, 4197704, 4197257, 4198311, 4197475, 4198283, 4198222, 4196299, 4198250, 4198230, 4196996, 4198149, 4198315, 4197312, 4198327, 4199252, 4198181, 4198221, 4198316, 4198154, 4198244, 4196920, 4196943, 4198325, 4198320, 4196975, 4198249];
VECTOR_UINT_STR_1 = ["4196330", "4196812", "4198245", "4198550", "4196885", "4197941", "4197659", "4196640", "4196980", "4196368", "4196795", "4197527", "4196374", "4196672", "4197016", "4197661", "4197014", "4197449", "4197615", "4196330", "4196579", "4196714", "4196835", "4196808", "4196786", "4197947", "4196473", "4196646", "4197939", "4197928", "4196366", "4197926", "4197559", "4196333", "4198850", "4196840", "4197927", "4196511", "4197938", "4196812", "4197925", "4197526", "4196312", "4196804", "4197528", "4196682", "4196954", "4196409", "4196258", "4198177", "4196291", "4198245", "4198180", "4196216", "4198277", "4196263", "4198280", "4198276", "4198282", "4198201", "4198279", "4197004", "4198211", "4197011", "4196759", "4197097", "4196512", "4197018", "4198236", "4198304", "4196397", "4198237", "4198312", "4198198", "4198199", "4198259", "4198310", "4198305", "4197201", "4198160", "4198326", "4198189", "4197704", "4197257", "4198311", "4197475", "4198283", "4198222", "4196299", "4198250", "4198230", "4196996", "4198149", "4198315", "4197312", "4198327", "4199252", "4198181", "4198221", "4198316", "4198154", "4198244", "4196920", "4196943", "4198325", "4198320", "4196975", "4198249"];
UNIT_ARR = [1, 2, 3, 4, 5, 6, 0xfffffff1, 0xfffffff2];
describe('bytearray', function() {
it('should read/write dynamic length utf correctly', function() {
var buf;
buf = new Buffer(2 + FIXTURE_UTF_BYTE_LENGTH);
bytearray.writeUTF(buf, FIXTURE_UTF);
buf.toString('hex').should.eql(FIXTURE_UTF_BUFF.toString('hex'));
return bytearray.readUTF(buf, 0).should.eql(FIXTURE_UTF);
});
it('should conver utf string to buffer correctly', function() {
var buf, byteLength, str;
str = "中午侧阿凡达是否违反片假名ニホンゴ罗马音nihon go 将( المنهج الواضح لتعل&#...";
byteLength = Buffer.byteLength(str);
buf = bytearray.utfStringToBuf(str);
bytearray.readUnsignedShort(buf, 0).should.eql(byteLength);
console.log("[bytearray_test::test utfStringToBuf] buf:" + (buf.toString('hex')));
return buf.slice(2).toString('hex').should.eql((new Buffer(str)).toString('hex'));
});
it('should able to write/read an uint vector', function() {
var arr, buf;
buf = new Buffer(VECTOR_UINT_1.length * 4 + 2);
bytearray.writeUnsignedIntArray(buf, VECTOR_UINT_1);
arr = bytearray.readUnsignedIntArray(buf, 0);
console.log("[bytearray_test::write/read an uint vector] arr:" + arr);
return arr.join(',').should.eql(VECTOR_UINT_1.join(','));
});
it('should able to write/read an string vector as an uint vector', function() {
var arr, buf;
buf = new Buffer(VECTOR_UINT_STR_1.length * 4 + 2);
bytearray.writeUnsignedIntArray(buf, VECTOR_UINT_STR_1);
arr = bytearray.readUnsignedIntArray(buf, 0);
console.log("[bytearray_test::write/read an uint vector] arr:" + arr);
return arr.join(',').should.eql(VECTOR_UINT_1.join(','));
});
it('should read and write UTFBytes correctly', function() {
var buf, buf2, byteLength, str;
str = "hellow, how are you";
byteLength = Buffer.byteLength(str);
buf = new Buffer(byteLength);
bytearray.writeUTFBytes(buf, str);
buf2 = new Buffer(str);
buf.toString('hex').should.equal(buf2.toString('hex'));
buf.position.should.equal(byteLength);
return bytearray.readUTFBytes(buf, byteLength, 0).should.equal(str);
});
return it('should read and write Float correctly', function() {
var buf, i, orgin, readback, sample, _i, _j, _ref, _ref1, _results;
sample = [321.324241, 0.323131, 4242.5435, 0.43242342];
buf = new Buffer(sample.length * 4);
for (i = _i = 0, _ref = sample.length; _i < _ref; i = _i += 1) {
bytearray.writeFloat(buf, sample[i]);
}
buf.position = 0;
_results = [];
for (i = _j = 0, _ref1 = sample.length; _j < _ref1; i = _j += 1) {
orgin = sample[i];
readback = bytearray.readFloat(buf);
console.log("[bytearray_test::Float test] orgin:" + orgin + ", readback:" + readback);
_results.push(Math.abs(readback - orgin).should.below(0.01));
}
return _results;
});
});
}).call(this);

36
proxy/node_modules/bytearray/package.json generated vendored Normal file
View File

@ -0,0 +1,36 @@
{
"name": "bytearray",
"description": "a Node.JS module for Buffer processing exposes API similar to ByteArray of ActionScript",
"version": "0.1.3",
"homepage": "https://github.com/yi/node-bytearray",
"author": {
"name": "yi",
"email": "yi2004@gmail.com"
},
"repository": {
"type": "git",
"url": "git://github.com/yi/node-bytearray.git"
},
"bugs": {
"url": "https://github.com/yi/node-bytearray/issues"
},
"licenses": [
{
"type": "MIT",
"url": "https://github.com/yi/node-bytearray/blob/master/LICENSE-MIT"
}
],
"main": "lib/bytearray",
"engines": {
"node": ">= 0.8.0"
},
"scripts": {
"test": "mocha tests/bytearray_test.js"
},
"devDependencies": {
"chai": ">=1.2.0",
"mocha": ">=1.3.2",
"should": ">=1.1.0"
},
"keywords": ["buffer","buf","endian","actionscript","bytearray"]
}

437
proxy/node_modules/bytearray/src/bytearray.coffee generated vendored Normal file
View File

@ -0,0 +1,437 @@
###
# a collection of utility methods for Buffer
#
#
# 1. Actionscript ByteArray
# 2. ActionScript big endian endian
#
###
module.exports =
# Reads a UTF-8 string from the byte stream. The string is assumed to be prefixed with an unsigned short indicating the length in bytes.
# @param {Buff} buf
# @param {int} [offset] optional, specify the offset where read should beging
readUTF : (buf, offset)->
return null unless Buffer.isBuffer buf
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
return null if buf.length <= offset + 2
len = buf.readUInt16BE(offset)
#console.log "[readUTF] buf.position:#{buf.position}, buf.length:#{buf.length}, offset:#{offset}, len:#{len} "
return null if buf.length < len + offset
offset += 2
buf.position = offset + len
return buf.toString 'utf8', offset, offset+len
# Reads a sequence of UTF-8 bytes specified by the length parameter from the byte stream and returns a string.
# @param {Buff} buf
# @param {uint} length, number of bytes to read
# @param {int} [offset] optional, specify the offset where read should beging
readUTFBytes : (buf, length, offset)->
return null unless Buffer.isBuffer buf
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
return null if buf.length <= offset
buf.position = offset + length
#console.log "[bytearray::readUTFBytes] buf:#{buf}, offset:#{offset}"
return buf.toString('utf8', offset, offset + length)
# @param {Buff} buf
# @param {int} [offset] optional, specify the offset where read should beging
readFixLengthASCII : (buf, offset) ->
return null unless Buffer.isBuffer buf
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
return null if buf.length <= offset + 2
len = buf.readUInt8(offset)
return null if buf.length < len + offset
offset += 1
buf.position = offset + len
buf.toString 'utf8', offset, offset+len
# Reads an unsigned 16-bit integer from the byte stream.
# @param {Buff} buf
# @param {int} [offset] optional, specify the offset where read should beging
readUnsignedShort : (buf, offset)->
return 0 unless Buffer.isBuffer buf
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.position = offset + 2
return buf.readUInt16BE offset
# Reads a 16-bit integer from the byte stream.
# @param {Buff} buf
# @param {int} [offset] optional, specify the offset where read should beging
readShort : (buf, offset)->
return 0 unless Buffer.isBuffer buf
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.position = offset + 2
buf.readInt16BE offset
# co-read to actionscript's ByteArray.readUnsignedByte
# @param {Buff} buf
# @param {int} [offset] optional, specify the offset where read should beging
readUnsignedByte : (buf, offset)->
return 0 unless Buffer.isBuffer buf
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.position = offset + 1
buf.readUInt8 offset
# Reads a byte from the byte stream.
# @param {Buff} buf
# @param {int} [offset] optional, specify the offset where read should beging
readByte : (buf, offset)->
return 0 unless Buffer.isBuffer buf
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.position = offset + 1
buf.readInt8 offset
# Reads an unsigned byte from the byte stream.
# @param {Buff} buf
# @param {int} [offset] optional, specify the offset where read should beging
readUnsignedInt: (buf, offset)->
return 0 unless Buffer.isBuffer buf
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.position = offset + 4
buf.readUInt32BE offset
# Reads a signed 32-bit integer from the byte stream.
# @param {Buff} buf
# @param {int} [offset] optional, specify the offset where read should beging
readInt: (buf, offset)->
return 0 unless Buffer.isBuffer buf
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.position = offset + 4
buf.readInt32BE offset
# Reads a signed 32-bit integer from the byte stream.
# @param {Buff} buf
# @param {int} [offset] optional, specify the offset where read should beging
readFloat : (buf, offset)->
return 0 unless Buffer.isBuffer buf
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.position = offset + 4
buf.readFloatLE offset
# TODO:
# this is a quick hack, should implement a proper endian swicher
# ty 2013-10-08
# @param {Buff} buf
# @param {int} [offset] optional, specify the offset where read should beging
readUnsignedIntArray:(buf, offset)->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
len = buf.readUInt16BE(offset) >>> 2 # *4 bytes for an int
offset += 2
arr = []
if len is 0 or len > 1024
buf.position = offset
return arr
while(len > 0)
a = buf.readUInt32BE(offset)
arr.push(a)
offset += 4
len -= 1
buf.position = offset
return arr
# @param {Buff} buf
# @param {uint} value
# @param {int} [offset] optional, specify the offset where read should beging
writeUnsignedInt : (buf, value, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
#console.log "[msg] buf.length:#{buf.length}, offset:#{offset}"
buf.writeUInt32BE value, offset
buf.position = offset + 4
return
# @param {Buff} buf
# @param {int} value
# @param {int} [offset] optional, specify the offset where read should beging
writeInt : (buf, value, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.writeInt32BE value, offset
buf.position = offset + 4
return
# @param {Buff} buf
# @param {int} value
# @param {int} [offset] optional, specify the offset where read should beging
writeFloat : (buf, value, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.writeFloatLE value, offset
# TODO:
# this is a quick hack, should implement a proper endian swicher
# ty 2013-10-08
buf.position = offset + 4
return
# @param {Buff} buf
# @param {ushort} value
# @param {int} [offset] optional, specify the offset where read should beging
writeUnsignedShort: (buf, value, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.writeUInt16BE value, offset
buf.position = offset + 2
return
# @param {Buff} buf
# @param {short} value
# @param {int} [offset] optional, specify the offset where read should beging
writeShort: (buf, value, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.writeInt16BE value, offset
buf.position = offset + 2
return
# @param {Buff} buf
# @param {ubyte} value
# @param {int} [offset] optional, specify the offset where read should beging
writeUnsignedByte: (buf, value, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.writeUInt8 value, offset
buf.position = offset + 1
return
# @param {Buff} buf
# @param {byte} value
# @param {int} [offset] optional, specify the offset where read should beging
writeByte: (buf, value, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.writeInt8 value, offset
buf.position = offset + 1
return
# @param {Buff} buf
# @param {Boolean} value
# @param {int} [offset] optional, specify the offset where read should beging
writeBoolean: (buf, value, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
value = if value then 1 else 0
buf.writeInt8 value, offset
buf.position = offset + 1
return
# ASCII bytes中写入给定的字符串 position
# buf : Buffer
# str :
# maxNumOfChar :
# offset :
writeFixLengthASCII : (buf, str, maxNumOfChar, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.writeUInt8 maxNumOfChar, offset
offset += 1 #+1 1byte的ascii
buf.fill(0x20, offset, offset + maxNumOfChar) # buf
buf.write str, offset, maxNumOfChar, 'ascii'
buf.position = offset + maxNumOfChar
return
# UTF-8 bytes中写入给定的字符串 position
# buf : Buffer
# str :
# maxNumOfChar :
# offset :
writeFixLengthUTF: (buf, str, maxNumOfChar, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
maxNumOfChar *= 6 # utf-8 char 6 byte
buf.writeUInt16BE maxNumOfChar, offset
offset += 2 # +2 2byte的utf长度
buf.fill(0x20, offset, offset + maxNumOfChar) # buf
buf.write str, offset, maxNumOfChar, 'utf8'
buf.position = offset + maxNumOfChar
return
# UTF-8 bytes中写入动态长度的字符串 position
# buf : Buffer
# str :
# offset :
writeUTF: (buf, str, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
byteLength = Buffer.byteLength(str)
buf.writeUInt16BE(byteLength , offset)
offset += 2 # +2 2byte的utf长度
buf.write(str, offset)
buf.position = offset + byteLength
return
# UTF-8 bytes中写入动态长度的字符串 position
# buf : Buffer
# str :
# offset :
writeUTFBytes: (buf, str, offset) ->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
buf.write(str, offset)
buf.position = offset + Buffer.byteLength(str)
return
# UTF-8 bytes中写入动态长度的字符串 position
# buf : Buffer
# strArray :
# offset :
writeUTFArray:(buf,strArray,offset)->
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
unless strArray? and strArray.length>0
buf.writeUInt16BE(0 , offset)
buf.position=offset+2
return
buf.writeUInt16BE(strArray.length , offset)
offset += 2 # +2 2byte的utf长度
for str in strArray
byteLength = Buffer.byteLength(str)
buf.writeUInt16BE(byteLength , offset)
offset += 2 # +2 2byte的utf长度
buf.write(str, offset)
offset += byteLength
buf.position=offset
getByteLengthOfUTFArray:(strArray)->
len=2
return len unless strArray? and strArray.length>0
for str in strArray
len=len+2+Buffer.byteLength(str)
return len
# int
# @param buf : Buffer
# @param arr :
# @param offset :
# @param fixedLength :
writeUnsignedIntArray:(buf, arr, fixedLength = -1, offset)->
arr = arr || [] # make sure argument arr is usable
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
n = arr.length
if fixedLength > 0 and fixedLength isnt n
# user require to write a fixed length of the given array
if fixedLength < n
arr = arr.slice(0, fixedLength)
# NOTE splice array arr.splice(fixedLength - n)
else
arr = arr.concat() # make a copy of the given arr
arr.length = fixedLength
n = fixedLength
n = n << 2 # *4 bytes for an int
buf.writeUInt16BE(n, offset)
offset += 2
for i in arr
buf.writeUInt32BE( parseInt(i,10) || 0 , offset)
offset += 4
buf.position = offset
return
# int数组要写入成二进制时所占的byte长度
# @param {int[]} arr an integer array
getByteLengthOfIntArray : (arr) ->
(arr.length << 2) + 2
# short
# @param buf : Buffer
# @param arr :
# @param offset :
# @param fixedLength :
writeUnsignedShortArray:(buf, arr, fixedLength = -1, offset)->
#console.log "[offset 1]:#{offset}"
arr = arr || [] # make sure argument arr is usable
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
#console.log "[offset 2]:#{offset}"
n = arr.length
if fixedLength > 0 and fixedLength isnt n
# user require to write a fixed length of the given array
if fixedLength < n
arr = arr.slice(0, fixedLength)
# NOTE splice array arr.splice(fixedLength - n)
else
arr = arr.concat() # make a copy of the given arr
arr.length = fixedLength
n = fixedLength
n = n << 1 # * 2 bytes for a short
#console.log "[offset]:#{offset}"
buf.writeUInt16BE(n, offset)
offset += 2
for i in arr
buf.writeUInt16BE( parseInt(i, 10) || 0 , offset)
offset += 2
buf.position = offset
return
# buf position byte
getBytesAvailable : (buf) ->
return if buf? then buf.length - (buf.position || 0) else 0
# buf的当前position位置length的byte片段buf的position属性
scrap : (buf, length) ->
return null unless buf? and length > 0
offset = (buf.position || 0)
return null if length + offset > buf.length
result = new Buffer(length)
buf.copy(result, 0, offset, offset + length)
buf.position = offset + length
return result
# buf buf
duplicate : (buf) ->
n = buf.length || 0
return null if n is 0
result = new Buffer(n)
buf.copy result, 0, 0, n
return result
# convert an input str to buffer by utf8 encoding, and add byte length by a short at the begine of the buffer
utfStringToBuf : (str) ->
str = String(str || '')
n = Buffer.byteLength(str, 'utf8')
buf = new Buffer(n+2)
buf.writeUInt16BE(n,0)
buf.write(str, 2)
return buf
#buf并且buf length >0
isAvailableBuf:(buf)->
return Buffer.isBuffer(buf) and buf.length>0
# int
# @param buf : Buffer
# @param arr :
# @param offset :
# @param fixedLength :
writeIntArray:(buf, arr, fixedLength = -1, offset)->
arr = arr || [] # make sure argument arr is usable
offset = if offset < 0 then buf.length + offset else (if offset is 0 then 0 else offset || buf.position || 0)
n = arr.length
if fixedLength > 0 and fixedLength isnt n
# user require to write a fixed length of the given array
if fixedLength < n
arr = arr.slice(0, fixedLength)
# NOTE splice array arr.splice(fixedLength - n)
else
arr = arr.concat() # make a copy of the given arr
arr.length = fixedLength
n = fixedLength
n = n << 2 # *4 bytes for an int
buf.writeUInt16BE(n, offset)
offset += 2
for i in arr
buf.writeInt32BE( parseInt(i,10) || 0 , offset)
offset += 4
buf.position = offset
return

View File

@ -0,0 +1,86 @@
require 'mocha'
should = require 'should'
bytearray = require '../byteArray'
FIXTURE_UTF = "这个LED花洒有意思@陈中 可建议 @吴海 在桔子酒店引入,"
FIXTURE_UTF_LENGTH = FIXTURE_UTF.length
FIXTURE_UTF_BYTE_LENGTH = Buffer.byteLength(FIXTURE_UTF)
FIXTURE_UTF_BUFF = new Buffer(2 + FIXTURE_UTF_BYTE_LENGTH)
FIXTURE_UTF_BUFF.writeUInt16BE( FIXTURE_UTF_BYTE_LENGTH, 0)
FIXTURE_UTF_BUFF.write(FIXTURE_UTF, 2)
VECTOR_UINT_1 = [4196330,4196812,4198245,4198550,4196885,4197941,4197659,4196640,4196980,4196368,4196795,4197527,4196374,4196672,4197016,4197661,4197014,4197449,4197615,4196330,4196579,4196714,4196835,4196808,4196786,4197947,4196473,4196646,4197939,4197928,4196366,4197926,4197559,4196333,4198850,4196840,4197927,4196511,4197938,4196812,4197925,4197526,4196312,4196804,4197528,4196682,4196954,4196409,4196258,4198177,4196291,4198245,4198180,4196216,4198277,4196263,4198280,4198276,4198282,4198201,4198279,4197004,4198211,4197011,4196759,4197097,4196512,4197018,4198236,4198304,4196397,4198237,4198312,4198198,4198199,4198259,4198310,4198305,4197201,4198160,4198326,4198189,4197704,4197257,4198311,4197475,4198283,4198222,4196299,4198250,4198230,4196996,4198149,4198315,4197312,4198327,4199252,4198181,4198221,4198316,4198154,4198244,4196920,4196943,4198325,4198320,4196975,4198249]
VECTOR_UINT_STR_1 = ["4196330","4196812","4198245","4198550","4196885","4197941","4197659","4196640","4196980","4196368","4196795","4197527","4196374","4196672","4197016","4197661","4197014","4197449","4197615","4196330","4196579","4196714","4196835","4196808","4196786","4197947","4196473","4196646","4197939","4197928","4196366","4197926","4197559","4196333","4198850","4196840","4197927","4196511","4197938","4196812","4197925","4197526","4196312","4196804","4197528","4196682","4196954","4196409","4196258","4198177","4196291","4198245","4198180","4196216","4198277","4196263","4198280","4198276","4198282","4198201","4198279","4197004","4198211","4197011","4196759","4197097","4196512","4197018","4198236","4198304","4196397","4198237","4198312","4198198","4198199","4198259","4198310","4198305","4197201","4198160","4198326","4198189","4197704","4197257","4198311","4197475","4198283","4198222","4196299","4198250","4198230","4196996","4198149","4198315","4197312","4198327","4199252","4198181","4198221","4198316","4198154","4198244","4196920","4196943","4198325","4198320","4196975","4198249"]
UNIT_ARR = [1,2,3,4,5,6,0xfffffff1, 0xfffffff2]
describe 'bytearray', ->
it 'should read/write dynamic length utf correctly', ->
buf = new Buffer(2 + FIXTURE_UTF_BYTE_LENGTH)
bytearray.writeUTF(buf, FIXTURE_UTF)
#console.log "[bytearray_test::] buf:#{buf.toString('hex')}"
buf.toString('hex').should.eql(FIXTURE_UTF_BUFF.toString('hex'))
#console.log "[bytearray_test::] bytearray.readUTF(buf, 0):#{bytearray.readUTF(buf, 0)}"
bytearray.readUTF(buf, 0).should.eql(FIXTURE_UTF)
it 'should conver utf string to buffer correctly', ->
str = "中午侧阿凡达是否违反片假名ニホンゴ罗马音nihon go 将( المنهج الواضح لتعل&#..."
byteLength = Buffer.byteLength(str)
buf = bytearray.utfStringToBuf(str)
bytearray.readUnsignedShort(buf,0).should.eql(byteLength)
console.log "[bytearray_test::test utfStringToBuf] buf:#{buf.toString('hex')}"
buf.slice(2).toString('hex').should.eql((new Buffer(str)).toString('hex'))
it 'should able to write/read an uint vector', ->
buf = new Buffer(VECTOR_UINT_1.length * 4 + 2)
bytearray.writeUnsignedIntArray(buf, VECTOR_UINT_1)
arr = bytearray.readUnsignedIntArray(buf, 0)
console.log "[bytearray_test::write/read an uint vector] arr:#{arr}"
arr.join(',').should.eql(VECTOR_UINT_1.join(','))
it 'should able to write/read an string vector as an uint vector', ->
buf = new Buffer(VECTOR_UINT_STR_1.length * 4 + 2)
bytearray.writeUnsignedIntArray(buf, VECTOR_UINT_STR_1)
arr = bytearray.readUnsignedIntArray(buf, 0)
console.log "[bytearray_test::write/read an uint vector] arr:#{arr}"
arr.join(',').should.eql(VECTOR_UINT_1.join(','))
it 'should read and write UTFBytes correctly' , ->
str = "hellow, how are you"
byteLength = Buffer.byteLength(str)
buf = new Buffer byteLength
bytearray.writeUTFBytes buf, str
buf2 = new Buffer str
buf.toString('hex').should.equal(buf2.toString('hex'))
buf.position.should.equal(byteLength)
bytearray.readUTFBytes(buf, byteLength, 0).should.equal str
it 'should read and write Float correctly' , ->
sample = [321.324241, 0.323131, 4242.5435, 0.43242342]
buf = new Buffer sample.length * 4
for i in [0...sample.length] by 1
bytearray.writeFloat buf, sample[i]
buf.position = 0
for i in [0...sample.length] by 1
orgin = sample[i]
readback = bytearray.readFloat(buf)
console.log "[bytearray_test::Float test] orgin:#{orgin}, readback:#{readback}"
Math.abs(readback - orgin).should.below(0.01)

24
proxy/package-lock.json generated Normal file
View File

@ -0,0 +1,24 @@
{
"name": "proxy",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "proxy",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"bytearray": "^0.1.3"
}
},
"node_modules/bytearray": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/bytearray/-/bytearray-0.1.3.tgz",
"integrity": "sha512-oEKhhGYMfEdfnp4yViXVeauXLLYLj0hs8cQpJmu0JXbhuVX1iTeVmZ2IW4QtXhBcZitzOZ6pYNRvMDJRl5/0og==",
"engines": {
"node": ">= 0.8.0"
}
}
}
}

15
proxy/package.json Normal file
View File

@ -0,0 +1,15 @@
{
"name": "proxy",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"bytearray": "^0.1.3"
}
}