tcp-tunnel-socket
Version:
Mixing multiple port data into one port channel
236 lines (217 loc) • 6 kB
JavaScript
var net=require('net');
var fs=require('fs');
var toolkit={};
/**
* [readMixBuffer 解析混合数据流]
* @param {[buffer]} buf [混合数据流]
* @return {[object]} [解析之后的数据格式object]
*/
toolkit.readMixBuffer=function(buf){
var mix=buf.slice(0,3);
var mixbuf = new Buffer("mix");
if(!mix.equals(mixbuf)){
return {mix:false};
}
var L=buf.length;
var index=buf.slice(3,5).readUInt16BE(0);
var id=buf.slice(5,13).toString();
var data=buf.slice(13);
var portstr=index+"";
if(typeof(index)!=="number"){
return {mix:false};
}
if(index>65535){
return {mix:false};
}
if(!id.match(/\d{8}/g)){
return {mix:false};
}
return {
mix:true,
index:index,
id:id,
data:data
};
}
/**
* [removeBuffer 移除子buffer]
* @param {[buffer]} buf [main buffer]
* @param {[buffer]} subuff [sub buffer]
* @return {[buffer]} [result buffer]
*/
toolkit.removeBuffer=function(buf,subuff){
var pos=buf.indexOf(subuff);
var L=subuff.length;
var A=buf.slice(0,pos);
var B=buf.slice(pos+L);
var data= Buffer.concat([A,B]);
return data;
}
/**
* [writeMixBuffer 组装混合流的数据包]
* @param {[number]} index [混合流之前数据的端口]
* @param {[string]} id [唯一标识符]
* @param {[buffer]} buf [混合之前的buffer数据]
* @return {[buffer]} [混合之后的buffer]
*/
toolkit.writeMixBuffer=function(index, id, buf){
var mix= new Buffer("mix");
var bufindex= new Buffer(2);
bufindex.writeUInt16BE(index,0);
var bufid = new Buffer(id);
var data= Buffer.concat([mix,bufindex,bufid,buf]);
return data;
}
/**
* [checkreadBuffer 检查混合包是否有误]
* @param {[buffer]} data [description]
* @param {[string]} log [description]
* @return {[buffer]} [description]
*/
toolkit.checkreadBuffer=function(data,log){
var mixObj = toolkit.readMixBuffer(data);
console.log("==========="+log+"==============");
if(!mixObj.mix){
return false;
}
if(typeof(mixObj.index)!=="number"){
console.log("数据异常!index");
return false;
}
if(mixObj.id.length!==8){
console.log("数据异常!id");
return false;
}
if(mixObj.data.length!==data.length-13){
console.log("数据异常!data");
console.log(mixObj.data.length,data.length);
console.log("id="+mixObj.id+"\n");
console.log("index="+mixObj.index+"\n");
console.log("data=",data);
return false;
}
return true;
}
/**
* [uuid 唯一id,8位字符串,待优化]
* @return {[string]} [字符串id]
*/
toolkit.uuid=function(){
var str=parseInt(Math.random()*100000000)+"";
var L=str.length;
if(L==8){
return str;
}
var M=8-L;
for(var i=1;i<=8-L;i++){
str=str+"0";
}
if(str.length!==8){
console.log("error str.length!==8");
}
return str;
}
/**
* [clientServer 客户端即时创建客户端tcpserver,提供给客户端自己使用127.0.0.1来调用]
* @param {[number]} port [客户端本地端口]
* @param {[socket]} mixClient [混合数据流句柄]
* @param {Function} callback [回调]
*/
toolkit.clientServer=function(index, config, ws){
var self=this;
var port=config.localport[index];
var tcpServer = net.createServer(function(socket){
var id=toolkit.uuid();
self.socketList[index+""][id]=socket;
//收到浏览器或其他客户端发来的数据
socket.on("data",function(data){
var buf=toolkit.writeMixBuffer(index,id,data);
toolkit.checkreadBuffer(buf,"client server "+port);
var mixObj = toolkit.readMixBuffer(buf);
if(!mixObj.mix){
console.log("toolkit.clientServer 数据异常!mix");
return false;
}
ws.send(buf);
});
socket.on('timeout', function(){
console.log("socket timeout");
});
var fn=function(error){
console.log(error);
setTimeout(function(){
delete self.socketList[index+""][id];
},1000);
}
socket.on("end",fn);
socket.on("error",fn);
socket.on("close",fn);
});
tcpServer.on('error', function(err){
throw err;
});
tcpServer.listen(port);
}
/**
* [clientConnect 服务器端client连接到各个提供服务器的host:port
* 暂时只提供服务器本地host
* mixserver发送给singclient的是解析后的直接流
* singleclient发送给mixserver的是加头之后的混合流
* ]
* @param {[string]} id [socket唯一标识符]
* @param {[number]} index [序号]
* @param {[socket]} mixSocket [服务器端主服务器socket句柄]
* @param {Function} fn [连接成功回调]
* @return {[object]} [client连接句柄]
*/
toolkit.clientConnect=function(id,index,address,ws,fn){
var singleClient = net.createConnection(address, function(){
console.log("connect ok");
console.log();
if(!toolkit.socketList[index+""]){
toolkit.socketList[index+""]={};
}
toolkit.socketList[index+""][id]=singleClient;
fn&&fn(singleClient);
});
singleClient.on('data', function(buf){
var data=toolkit.writeMixBuffer(index,id,buf);
toolkit.checkreadBuffer(data,"singleClient发送给mixServer");
ws.send(data);
});
singleClient.on('end', function(){
console.log("end");
setTimeout(function(){
delete toolkit.socketList[index+""][id];
},1000);
});
singleClient.on('timeout', function(){
console.log(" singleClient timeout");
});
return singleClient;
}
/**
* [readConfig 读取配置]
* @param {[type]} path [配置文件路径]
* @param {Function} fn [回调]
*/
toolkit.readConfig=function(path,fn){
var flag=fs.existsSync(path);
if(!flag){
fn&&fn("file not exist");
return;
}
var data=fs.readFileSync(path,"utf-8");
try{
var config=JSON.parse(data);
}
catch(e){
fn&&fn("JSON.parse error");
console.log("JSON.parse error");
return;
}
fn&&fn(null,config);
return config;
}
toolkit.socketList={};
module.exports = toolkit;