2019-07-10 04:01:15 +00:00
|
|
|
/*
|
|
|
|
* @project: TERA
|
|
|
|
* @version: Development (beta)
|
|
|
|
* @license: MIT (not for evil)
|
|
|
|
* @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
|
|
|
|
* Web: https://terafoundation.org
|
|
|
|
* Twitter: https://twitter.com/terafoundation
|
|
|
|
* Telegram: https://t.me/terafoundation
|
|
|
|
*/
|
|
|
|
|
|
|
|
"use strict";
|
2019-07-12 14:46:26 +00:00
|
|
|
import * as net from 'net'
|
2019-07-10 09:53:52 +00:00
|
|
|
// import dgram = require("dgram");
|
2019-07-10 04:01:15 +00:00
|
|
|
import * as crypto from 'crypto';
|
2019-07-16 04:22:39 +00:00
|
|
|
import { secp256k1, RBTree } from "./library"
|
2019-07-10 09:28:08 +00:00
|
|
|
import "./crypto-library"
|
2019-07-11 05:35:16 +00:00
|
|
|
import CConnect from './connect'
|
2019-07-13 02:22:28 +00:00
|
|
|
import { STreeBuffer } from './base';
|
2019-07-20 05:12:21 +00:00
|
|
|
import CNode, { TeraSocket } from './node';
|
2019-07-10 04:01:15 +00:00
|
|
|
const HARD_PACKET_PERIOD = 20;
|
|
|
|
global.BUF_TYPE = 1;
|
|
|
|
global.STR_TYPE = 2;
|
|
|
|
global.MAX_STR_BUF_DATA = 200;
|
|
|
|
global.MAX_CONNECTION_ACTIVE = 40;
|
2019-07-11 07:52:17 +00:00
|
|
|
var MAX_CONNECTION_ANOTHER = 40;
|
2019-07-10 07:59:04 +00:00
|
|
|
const TRAFIC_LIMIT_NODE_1S = global.MAX_BLOCK_SIZE * 1.25;
|
2019-07-10 04:01:15 +00:00
|
|
|
const TRAFIC_LIMIT_1S = 8 * TRAFIC_LIMIT_NODE_1S;
|
2019-07-10 07:59:04 +00:00
|
|
|
global.STAT_PERIOD = global.CONSENSUS_PERIOD_TIME / 5;
|
|
|
|
const TRAFIC_LIMIT_SEND = TRAFIC_LIMIT_1S * global.STAT_PERIOD / 1000;
|
|
|
|
const TRAFIC_LIMIT_NODE = TRAFIC_LIMIT_NODE_1S * global.STAT_PERIOD / 1000;
|
2019-07-10 04:01:15 +00:00
|
|
|
const BUF_PACKET_SIZE = 32 * 1024;
|
|
|
|
global.FORMAT_POW_TO_CLIENT = "{addrArr:hash,HashRND:hash,MIN_POWER_POW_HANDSHAKE:uint,PubKeyType:byte,Sign:arr64,Reserve:arr33}";
|
|
|
|
global.FORMAT_POW_TO_SERVER = "{\
|
|
|
|
DEF_NETWORK:str15,\
|
2019-07-13 07:37:38 +00:00
|
|
|
DEF_VERSION:str9,\
|
2019-07-10 04:01:15 +00:00
|
|
|
DEF_CLIENT:str16, \
|
|
|
|
addrArr:addres, \
|
|
|
|
ToIP:str26,\
|
|
|
|
ToPort:uint16, \
|
|
|
|
FromIP:str26,\
|
|
|
|
FromPort:uint16, \
|
|
|
|
nonce:uint,\
|
|
|
|
Reconnect:byte,\
|
|
|
|
SendBytes:uint,\
|
|
|
|
PubKeyType:byte,\
|
|
|
|
Sign:arr64,\
|
|
|
|
SecretForReconnect:arr20,\
|
|
|
|
GrayConnect:byte,\
|
|
|
|
Reserve:arr14\
|
|
|
|
}";
|
|
|
|
const WorkStructPacketSend = {};
|
|
|
|
const FORMAT_PACKET_SEND_TCP = "{\
|
|
|
|
PacketSize:uint,\
|
|
|
|
NumXORRND:uint,\
|
|
|
|
Method:str25,\
|
|
|
|
NodeTime:time,\
|
|
|
|
Length:uint,\
|
|
|
|
ContextID:hash,\
|
|
|
|
TypeData:byte,\
|
|
|
|
Hash:hash,\
|
|
|
|
Data:data,\
|
|
|
|
}";
|
2019-07-11 05:35:16 +00:00
|
|
|
export default class CTransport extends CConnect {
|
2019-07-10 07:59:04 +00:00
|
|
|
UseRNDHeader
|
|
|
|
BAN_IP
|
|
|
|
CanSend
|
|
|
|
SendFormatMap
|
|
|
|
ActualNodes
|
|
|
|
SendTrafficFree
|
|
|
|
LoadedPacketNum
|
|
|
|
LoadedSocketNum
|
|
|
|
LoadBufSocketList
|
|
|
|
BusyLevel
|
|
|
|
LastTimeHard
|
|
|
|
LastTimeHardOK
|
|
|
|
HardPacketForSend
|
|
|
|
MethodTiming
|
|
|
|
CurrentTimeStart
|
|
|
|
CurrentTimeValues
|
|
|
|
SendStatNum
|
|
|
|
Server
|
|
|
|
ServerSign
|
2019-07-10 04:01:15 +00:00
|
|
|
constructor(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) {
|
|
|
|
super(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual)
|
|
|
|
this.UseRNDHeader = UseRNDHeader
|
|
|
|
this.BAN_IP = {}
|
|
|
|
this.ip = RunIP.trim()
|
|
|
|
this.port = RunPort
|
|
|
|
this.CanSend = 0
|
|
|
|
this.SendFormatMap = {}
|
2019-07-13 02:22:28 +00:00
|
|
|
this.ActualNodes = new RBTree(function(a: any, b: any): number {
|
2019-07-10 04:01:15 +00:00
|
|
|
if (b.Prioritet !== a.Prioritet)
|
|
|
|
return b.Prioritet - a.Prioritet;
|
|
|
|
return global.CompareArr(a.addrArr, b.addrArr);
|
|
|
|
})
|
|
|
|
this.SendTrafficFree = 0
|
|
|
|
this.LoadedPacketNum = 0
|
|
|
|
this.LoadedSocketNum = 0
|
|
|
|
setInterval(this.DoLoadBuf.bind(this), 1)
|
2019-07-13 02:22:28 +00:00
|
|
|
this.LoadBufSocketList = new RBTree(function(a: any, b: any): number {
|
2019-07-10 04:01:15 +00:00
|
|
|
if (b.SocketPrioritet !== a.SocketPrioritet)
|
|
|
|
return b.SocketPrioritet - a.SocketPrioritet;
|
|
|
|
return a.SocketNum - b.SocketNum;
|
|
|
|
})
|
|
|
|
this.BusyLevel = 0
|
|
|
|
this.LastTimeHard = 0
|
|
|
|
this.LastTimeHardOK = 0
|
|
|
|
setInterval(this.DoHardPacketForSend.bind(this), HARD_PACKET_PERIOD)
|
2019-07-13 02:22:28 +00:00
|
|
|
this.HardPacketForSend = new RBTree(function(a: any, b: any): number {
|
2019-07-10 04:01:15 +00:00
|
|
|
if (b.BlockProcessCount === a.BlockProcessCount)
|
|
|
|
return a.PacketNum - b.PacketNum;
|
|
|
|
else
|
|
|
|
return b.BlockProcessCount - a.BlockProcessCount;
|
|
|
|
})
|
|
|
|
setInterval(this.DoSendPacket.bind(this), 2)
|
|
|
|
setInterval(this.DoSendBuf.bind(this), 1)
|
|
|
|
var Map = {};
|
|
|
|
this.MethodTiming = Map
|
|
|
|
MethodTiming:
|
|
|
|
{
|
|
|
|
Map["TRANSFER"] = { Period: 700, Hot: 1 }
|
|
|
|
Map["TRANSFERTX"] = { Period: 700, Hot: 1 }
|
|
|
|
Map["TIME"] = { Period: 2000, LowVersion: 1, Hard: 1, Immediately: 1 }
|
|
|
|
Map["PING"] = { Period: 4000, LowVersion: 1, Hard: 1, Immediately: 1 }
|
|
|
|
Map["PONG"] = { Period: 0, LowVersion: 1, Immediately: 1 }
|
|
|
|
Map["ADDLEVELCONNECT"] = { Period: 1000, Hard: 1 }
|
|
|
|
Map["RETADDLEVELCONNECT"] = { Period: 0 }
|
|
|
|
Map["DISCONNECTHOT"] = { Period: 1000, Hard: 1 }
|
|
|
|
Map["GETMESSAGE"] = { Period: 1000, Hard: 1 }
|
|
|
|
Map["MESSAGE"] = { Period: 1000, Hard: 1 }
|
2019-07-10 07:59:04 +00:00
|
|
|
Map["TRANSACTION"] = { Period: global.PERIOD_GET_BLOCK, Hard: 1 }
|
|
|
|
Map["GETBLOCKHEADER"] = { Period: global.PERIOD_GET_BLOCK, Hard: 2, Process: global.STATIC_PROCESS }
|
|
|
|
Map["GETBLOCKHEADER100"] = { Period: global.PERIOD_GET_BLOCK, Hard: 2, Process: global.STATIC_PROCESS }
|
|
|
|
Map["GETBLOCK"] = { Period: global.PERIOD_GET_BLOCK, Hard: 2, Process: global.STATIC_PROCESS }
|
2019-07-10 04:01:15 +00:00
|
|
|
Map["GETNODES"] = { Period: 1000, Hard: 1, LowVersion: 1, IsAddrList: 1 }
|
|
|
|
Map["RETGETNODES"] = { Period: 0, IsAddrList: 1 }
|
|
|
|
Map["RETGETNODES2"] = { Period: 0, IsAddrList: 1 }
|
|
|
|
Map["GETCODE"] = { Period: 10000, Hard: 1, LowVersion: 1, Process: global.STATIC_PROCESS }
|
|
|
|
Map["RETBLOCKHEADER"] = { Period: 0 }
|
|
|
|
Map["RETBLOCKHEADER100"] = { Period: 0 }
|
|
|
|
Map["RETGETBLOCK"] = { Period: 0 }
|
|
|
|
Map["RETCODE"] = { Period: 0 }
|
|
|
|
Map["GETREST"] = { Period: 1000, Hard: 2, Process: global.STATIC_PROCESS }
|
|
|
|
Map["RETREST"] = { Period: 0 }
|
|
|
|
Map["GETSMART"] = { Period: 1000, Hard: 2, Process: global.STATIC_PROCESS }
|
|
|
|
Map["RETSMART"] = { Period: 0 }
|
|
|
|
}
|
|
|
|
if (!this.VirtualMode)
|
|
|
|
this.StartServer()
|
|
|
|
this.CurrentTimeStart = 0
|
|
|
|
this.CurrentTimeValues = {}
|
|
|
|
this.LoadNodesFromFile()
|
|
|
|
}
|
|
|
|
GetF(Method, bSend) {
|
|
|
|
var name = Method + "-" + bSend;
|
|
|
|
var format = this.SendFormatMap[name];
|
|
|
|
if (!format) {
|
|
|
|
var F = this.constructor[Method + "_F"];
|
|
|
|
if (typeof F === "function") {
|
|
|
|
format = { struct: F(bSend), length: 8096, wrk: {} }
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
format = "{}"
|
|
|
|
}
|
|
|
|
this.SendFormatMap[name] = format
|
|
|
|
}
|
|
|
|
return format;
|
|
|
|
}
|
|
|
|
SendF(Node, Info, Length) {
|
|
|
|
var format = this.GetF(Info.Method, true);
|
|
|
|
if (!Length)
|
|
|
|
Length = format.length
|
|
|
|
Info.Data = global.BufLib.GetBufferFromObject(Info.Data, format.struct, Length, format.wrk)
|
|
|
|
this.Send(Node, Info, 1)
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
DataFromF(Info, bSendFormat?) {
|
2019-07-10 04:01:15 +00:00
|
|
|
var format = this.GetF(Info.Method, bSendFormat);
|
|
|
|
try {
|
|
|
|
var Data = global.BufLib.GetObjectFromBuffer(Info.Data, format.struct, format.wrk);
|
|
|
|
return Data;
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
global.ToLog(e)
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ADD_CURRENT_STAT_TIME(Key, Value) {
|
2019-07-10 07:59:04 +00:00
|
|
|
var TimeNum = Math.floor(Date.now() / global.STAT_PERIOD);
|
2019-07-10 04:01:15 +00:00
|
|
|
if (this.CurrentTimeStart !== TimeNum)
|
|
|
|
this.CurrentTimeValues = {}
|
|
|
|
this.CurrentTimeStart = TimeNum
|
|
|
|
if (!this.CurrentTimeValues[Key])
|
|
|
|
this.CurrentTimeValues[Key] = 0
|
|
|
|
this.CurrentTimeValues[Key] += Value
|
|
|
|
}
|
|
|
|
GET_CURRENT_STAT_TIME(Key) {
|
2019-07-10 07:59:04 +00:00
|
|
|
var TimeNum = Math.floor(Date.now() / global.STAT_PERIOD);
|
2019-07-10 04:01:15 +00:00
|
|
|
if (this.CurrentTimeStart === TimeNum) {
|
|
|
|
var Value = this.CurrentTimeValues[Key];
|
|
|
|
if (Value === undefined)
|
|
|
|
return 0;
|
|
|
|
else
|
|
|
|
return Value;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RecalcSendStatictic() {
|
2019-07-10 07:59:04 +00:00
|
|
|
var TimeNum = Math.floor(Date.now() / global.STAT_PERIOD);
|
2019-07-10 04:01:15 +00:00
|
|
|
if (this.SendStatNum === TimeNum)
|
|
|
|
return;
|
|
|
|
this.SendStatNum = TimeNum
|
2019-07-10 07:59:04 +00:00
|
|
|
var Period = global.CONSENSUS_PERIOD_TIME / global.STAT_PERIOD;
|
2019-07-10 04:01:15 +00:00
|
|
|
this.SendTrafficFree = TRAFIC_LIMIT_SEND
|
|
|
|
var it = this.ActualNodes.iterator(), Node;
|
|
|
|
while ((Node = it.next()) !== null) {
|
|
|
|
{
|
|
|
|
var arr = Node.TrafficArr;
|
|
|
|
arr.push(Node.BufWriteLength)
|
|
|
|
Node.BufWriteLength = 0
|
|
|
|
if (arr.length > 5 * Period) {
|
|
|
|
arr.shift()
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (arr.length < 3 * Period)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
var arrAvg = [], arrK = [];
|
|
|
|
var valNext = CalcStatArr(arr, arrAvg, arrK, Period);
|
|
|
|
valNext = Math.min(valNext, TRAFIC_LIMIT_NODE)
|
|
|
|
Node.SendTrafficLimit = Math.min(this.SendTrafficFree, valNext * 1.1)
|
|
|
|
this.SendTrafficFree -= Node.SendTrafficLimit
|
|
|
|
}
|
|
|
|
Node.SendTrafficCurrent = 0
|
2019-07-11 05:35:16 +00:00
|
|
|
global.ADD_TO_STAT("MAX:NODE_TRAFFIC_LIMIT:" + global.NodeName(Node), 1000 / global.STAT_PERIOD * Node.SendTrafficLimit / 1024, 1)
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
|
|
|
this.SendTrafficFree += TRAFIC_LIMIT_NODE
|
|
|
|
global.ADD_TO_STAT("SEND_TRAFFIC_FREE", this.SendTrafficFree / 1024)
|
|
|
|
}
|
|
|
|
OnGetMethod(Info, CurTime) {
|
2019-07-10 07:59:04 +00:00
|
|
|
if (global.DEBUG_MODE) {
|
2019-07-10 04:01:15 +00:00
|
|
|
var Str = "";
|
|
|
|
if (Info.Data && Info.Data.Length)
|
|
|
|
Str = " LENGTH=" + Info.Data.Length
|
2019-07-11 05:35:16 +00:00
|
|
|
global.TO_DEBUG_LOG("GET:" + Info.Method + Str + " from: Node=" + global.NodeInfo(Info.Node))
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
|
|
|
if (global.ADDRLIST_MODE) {
|
|
|
|
var StrOK = ",HAND,GETNODES,";
|
|
|
|
if (StrOK.indexOf("," + Info.Method + ",") === - 1)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Info.Node.LastTime = CurTime - 0
|
|
|
|
if (Info.Context && typeof Info.Context.F === "function") {
|
|
|
|
Info.Context.F(Info, CurTime)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var F = this[Info.Method.toUpperCase()];
|
|
|
|
if (typeof F === "function") {
|
|
|
|
F.bind(this)(Info, CurTime)
|
|
|
|
}
|
|
|
|
else {
|
2019-07-10 07:59:04 +00:00
|
|
|
global.TO_ERROR_LOG("TRANSPORT", 20, "Method '" + Info.Method + "' not found Socket=*" + Info.Socket.ConnectID, "node", Info.Node)
|
2019-07-10 04:01:15 +00:00
|
|
|
this.AddCheckErrCount(Info.Node, 1, "Method not found")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
GetActualNodes() {
|
|
|
|
var Arr = [];
|
|
|
|
var it = this.ActualNodes.iterator(), Item;
|
|
|
|
while ((Item = it.next()) !== null) {
|
2019-07-11 05:35:16 +00:00
|
|
|
if (global.GetSocketStatus(Item.Socket) >= 100)
|
2019-07-10 04:01:15 +00:00
|
|
|
Arr.push(Item)
|
|
|
|
else {
|
|
|
|
this.DeleteNodeFromActive(Item)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Arr;
|
|
|
|
}
|
|
|
|
NodeIp(Node) {
|
|
|
|
if (Node.ip_arrival) {
|
|
|
|
return { ip: Node.ip_arrival, port: Node.port_arrival };
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return { ip: Node.ip, port: Node.port };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetXORHeader(buf, bForce) {
|
|
|
|
if (this.UseRNDHeader || bForce) {
|
|
|
|
var HashHashSign = global.shaarr(buf.slice(buf.length - 32, buf.length));
|
|
|
|
for (var i = 0; i < 32; i++)
|
|
|
|
buf[i] = HashHashSign[i] ^ buf[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
WasBanIP(rinfo) {
|
|
|
|
if (!rinfo || !rinfo.address)
|
|
|
|
return false;
|
|
|
|
var Key = "" + rinfo.address.trim();
|
|
|
|
var Stat = this.BAN_IP[Key];
|
|
|
|
if (Stat) {
|
2019-07-10 07:59:04 +00:00
|
|
|
if (Stat.TimeTo > (global.GetCurrentTime(0) - 0))
|
2019-07-10 04:01:15 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
NodeInBan(Node) {
|
|
|
|
return this.WasBanIP({ address: Node.ip });
|
|
|
|
}
|
|
|
|
DeleteNodeFromActiveByIP(ip) {
|
|
|
|
var Arr = this.GetActualNodes();
|
|
|
|
for (var i = 0; i < Arr.length; i++) {
|
|
|
|
var Node = Arr[i];
|
|
|
|
if (Node.ip === ip) {
|
|
|
|
this.DeleteNodeFromActive(Node)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
AddToBan(Node, Str) {
|
|
|
|
if (global.NeedRestart)
|
|
|
|
return;
|
|
|
|
this.DeleteNodeFromActive(Node)
|
|
|
|
if (!Node.ip)
|
|
|
|
return;
|
|
|
|
var Key = "" + Node.ip.trim();
|
|
|
|
if (!Node.DeltaBan)
|
|
|
|
Node.DeltaBan = 300
|
|
|
|
if (Node.DeltaBan > 1000000)
|
|
|
|
Node.DeltaBan = 1000000
|
|
|
|
Node.DeltaBan = Node.DeltaBan * 2
|
2019-07-10 07:59:04 +00:00
|
|
|
var TimeTo = (global.GetCurrentTime(0) - 0) + Node.DeltaBan * 1000;
|
2019-07-10 04:01:15 +00:00
|
|
|
this.BAN_IP[Key] = { TimeTo: TimeTo }
|
|
|
|
Node.BlockProcessCount = 0
|
|
|
|
this.DeleteNodeFromActiveByIP(Node.ip)
|
|
|
|
global.ADD_TO_STAT("AddToBan")
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
AddToBanIP(ip, Str, Period?) {
|
2019-07-10 04:01:15 +00:00
|
|
|
if (!Period)
|
|
|
|
Period = 600 * 1000
|
|
|
|
var Key = "" + ip.trim();
|
2019-07-10 07:59:04 +00:00
|
|
|
this.BAN_IP[Key] = { TimeTo: (global.GetCurrentTime(0) - 0) + Period }
|
2019-07-10 04:01:15 +00:00
|
|
|
this.DeleteNodeFromActiveByIP(ip)
|
|
|
|
global.ToLog("ADD TO BAN:: " + Key + " " + Str)
|
|
|
|
global.ADD_TO_STAT("AddToBanIP")
|
|
|
|
}
|
|
|
|
OnPacketTCP(Meta) {
|
|
|
|
var startTime = process.hrtime();
|
|
|
|
global.ADD_TO_STAT("USEPACKET")
|
|
|
|
var CurTime = global.GetCurrentTime();
|
|
|
|
Meta.Node.LastTime = CurTime - 0
|
|
|
|
if (Meta.MethodTiming.Process && Meta.MethodTiming.Process.Worker) {
|
|
|
|
var Data = this.DataFromF(Meta);
|
|
|
|
Meta.MethodTiming.Process.Worker.send({ cmd: Meta.Method, Data: Data, addrStr: Meta.Node.addrStr, Context: Meta.Context })
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.OnGetMethod(Meta, CurTime)
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
global.ADD_TO_STAT_TIME("MAX:TIME_USE_PACKET", startTime)
|
|
|
|
global.ADD_TO_STAT_TIME("TIME_USE_PACKET", startTime)
|
|
|
|
global.ADD_TO_STAT_TIME("MAX:TIME_USE_PACKET:" + Meta.Method, startTime)
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
GetBufFromData(Method, Data, TypeData, ContextID?) {
|
2019-07-10 04:01:15 +00:00
|
|
|
var BufData;
|
2019-07-10 07:59:04 +00:00
|
|
|
if (TypeData === global.BUF_TYPE) {
|
2019-07-10 04:01:15 +00:00
|
|
|
BufData = Data
|
|
|
|
}
|
|
|
|
else
|
2019-07-10 07:59:04 +00:00
|
|
|
if (TypeData === global.STR_TYPE) {
|
|
|
|
BufData = Buffer.from(Data.substr(0, global.MAX_STR_BUF_DATA))
|
2019-07-13 07:37:38 +00:00
|
|
|
} else {
|
2019-07-10 04:01:15 +00:00
|
|
|
if (Data === undefined) {
|
2019-07-10 07:59:04 +00:00
|
|
|
TypeData = global.BUF_TYPE
|
2019-07-10 04:01:15 +00:00
|
|
|
BufData = Buffer.alloc(0)
|
2019-07-13 07:37:38 +00:00
|
|
|
} else {
|
2019-07-10 04:01:15 +00:00
|
|
|
throw "ERROR TYPE DATA";
|
|
|
|
}
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
var BUF: any = {};
|
2019-07-10 04:01:15 +00:00
|
|
|
BUF.PacketSize = 0
|
|
|
|
BUF.NumXORRND = 0
|
|
|
|
BUF.Method = Method
|
|
|
|
BUF.NodeTime = global.GetCurrentTime()
|
|
|
|
BUF.TypeData = TypeData
|
|
|
|
BUF.Length = BufData.length
|
|
|
|
BUF.Data = BufData
|
|
|
|
BUF.ContextID = ContextID
|
|
|
|
BUF.Hash = this.GetHashFromData(BUF)
|
|
|
|
var BufWrite = global.BufLib.GetBufferFromObject(BUF, FORMAT_PACKET_SEND_TCP, BufData.length + 300, WorkStructPacketSend);
|
|
|
|
BufWrite.len = 0
|
|
|
|
global.BufLib.Write(BufWrite, BufWrite.length, "uint")
|
|
|
|
return BufWrite;
|
|
|
|
}
|
|
|
|
GetDataFromBuf(buf) {
|
|
|
|
try {
|
|
|
|
var Meta = global.BufLib.GetObjectFromBuffer(buf, FORMAT_PACKET_SEND_TCP, WorkStructPacketSend);
|
2019-07-13 07:37:38 +00:00
|
|
|
} catch (e) {
|
2019-07-10 07:59:04 +00:00
|
|
|
global.TO_ERROR_LOG("TRANSPORT", 640, "Error parsing Buffer")
|
2019-07-10 04:01:15 +00:00
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
var Hash = this.GetHashFromData(Meta);
|
|
|
|
if (global.CompareArr(Hash, Meta.Hash) !== 0) {
|
|
|
|
if (global.WATCHDOG_DEV)
|
|
|
|
global.ToLog("TRANSPORT", 645, "Error hash Buffer", 2)
|
|
|
|
return undefined;
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
if (Meta.TypeData === global.STR_TYPE) {
|
|
|
|
Meta.Data = Meta.Data.slice(0, global.MAX_STR_BUF_DATA).toString()
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
|
|
|
return Meta;
|
|
|
|
}
|
|
|
|
GetHashFromData(Info) {
|
|
|
|
return global.shaarr(Info.Method + Info.Length + "-" + (Info.NodeTime - 0));
|
|
|
|
}
|
2019-07-20 05:12:21 +00:00
|
|
|
OnGetFromTCP(Node: CNode, Socket: TeraSocket, Buf) {
|
2019-07-10 04:01:15 +00:00
|
|
|
if (!Node)
|
|
|
|
return;
|
|
|
|
if (!Node.Socket)
|
|
|
|
Node.Socket = Socket
|
|
|
|
if (!Socket.Buf || Socket.Buf.length === 0) {
|
|
|
|
Socket.Buf = Buf
|
2019-07-13 07:37:38 +00:00
|
|
|
} else {
|
2019-07-10 04:01:15 +00:00
|
|
|
Socket.Buf = Buffer.concat([Socket.Buf, Buf])
|
|
|
|
}
|
|
|
|
if (!Socket.SocketNum) {
|
|
|
|
this.LoadedSocketNum++
|
|
|
|
Socket.SocketNum = this.LoadedSocketNum
|
|
|
|
Socket.SocketPrioritet = Node.BlockProcessCount
|
|
|
|
}
|
|
|
|
this.LoadBufSocketList.insert(Socket)
|
|
|
|
}
|
|
|
|
DoLoadBuf() {
|
|
|
|
var Socket = this.LoadBufSocketList.min();
|
|
|
|
if (!Socket)
|
|
|
|
return;
|
|
|
|
this.LoadBufSocketList.remove(Socket)
|
|
|
|
if (Socket.WasClose)
|
|
|
|
return;
|
|
|
|
while (true) {
|
|
|
|
if (Socket.Buf && Socket.Buf.length > 6) {
|
|
|
|
global.ADD_TO_STAT("MAX:BUFFE_LOAD_SIZE", Socket.Buf.length / 1024)
|
|
|
|
Socket.Buf.len = 0
|
|
|
|
var PacketSize = global.BufLib.Read(Socket.Buf, "uint");
|
2019-07-10 07:59:04 +00:00
|
|
|
if (PacketSize > global.MAX_PACKET_LENGTH) {
|
2019-07-10 04:01:15 +00:00
|
|
|
this.SendCloseSocket(Socket, "MAX_PACKET_LENGTH")
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
if (Socket.Buf.length >= PacketSize) {
|
|
|
|
var data = Socket.Buf.slice(0, PacketSize);
|
|
|
|
Socket.Buf = Socket.Buf.slice(PacketSize, Socket.Buf.length)
|
|
|
|
var Res = this.DoDataFromTCP(Socket, data);
|
|
|
|
if (Res) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DoDataFromTCP(Socket, buf) {
|
|
|
|
this.LoadedPacketNum++
|
|
|
|
var Node = Socket.Node;
|
|
|
|
if (!Node)
|
|
|
|
return 0;
|
|
|
|
var startTime = process.hrtime();
|
|
|
|
global.ADD_TO_STAT("GETDATA(KB)", buf.length / 1024)
|
2019-07-11 05:35:16 +00:00
|
|
|
global.ADD_TO_STAT("GETDATA(KB):" + global.NodeName(Node), buf.length / 1024, 1)
|
2019-07-10 04:01:15 +00:00
|
|
|
if (!Node.TransferSize)
|
|
|
|
Node.TransferSize = 0
|
|
|
|
Node.TransferSize += buf.length / 1024
|
|
|
|
Node.TransferBlockNumFix = this.CurrentBlockNum
|
|
|
|
var Buf = this.GetDataFromBuf(buf);
|
|
|
|
if (!Buf) {
|
|
|
|
this.AddCheckErrCount(Node, 1, "Err GetDataFromBuf")
|
|
|
|
this.SendCloseSocket(Socket, "FORMAT_PACKET_SEND_TCP")
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
global.ADD_TO_STAT("GET:" + Buf.Method)
|
|
|
|
global.ADD_TO_STAT("GET:(KB)" + Buf.Method, buf.length / 1024)
|
2019-07-11 05:35:16 +00:00
|
|
|
global.ADD_TO_STAT("GET:" + Buf.Method + ":" + global.NodeName(Node), 1, 1)
|
2019-07-10 04:01:15 +00:00
|
|
|
var Param = this.MethodTiming[Buf.Method];
|
|
|
|
if (this.StopDoSendPacket(Param, Node, Buf.Method)) {
|
|
|
|
return 1;
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
if (!global.IsZeroArr(Buf.ContextID)) {
|
2019-07-10 04:01:15 +00:00
|
|
|
Buf.Context = global.ContextPackets.LoadValue(Buf.ContextID)
|
|
|
|
}
|
|
|
|
if (!Buf.Context) {
|
|
|
|
if (Param && Param.Period === 0 && Buf.Method !== "RETBLOCKHEADER") {
|
|
|
|
this.AddCheckErrCount(Node, 1)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Buf.Context = {}
|
|
|
|
}
|
|
|
|
Buf.Context.ContextID = Buf.ContextID
|
|
|
|
Buf.Node = Node
|
|
|
|
Buf.Socket = Socket
|
|
|
|
Buf.MethodTiming = Param
|
|
|
|
if (!global.ADDRLIST_MODE || Param.IsAddrList) {
|
|
|
|
if (Param.Hard) {
|
|
|
|
if (Param.Immediately && this.HardPacketForSend.size <= 3) {
|
|
|
|
this.OnPacketTCP(Buf)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Buf.PacketNum = this.LoadedPacketNum
|
|
|
|
Buf.BlockProcessCount = Node.BlockProcessCount
|
|
|
|
Buf.TimeLoad = Date.now()
|
|
|
|
this.HardPacketForSend.insert(Buf)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.OnPacketTCP(Buf)
|
|
|
|
}
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
global.ADD_TO_STAT_TIME("MAX:TIMEDOGETDATA", startTime)
|
2019-07-10 04:01:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
StopDoSendPacket(Param, Node, Name) {
|
2019-07-10 07:59:04 +00:00
|
|
|
var CurTime = global.GetCurrentTime(0) - 0;
|
2019-07-10 04:01:15 +00:00
|
|
|
if (!Param) {
|
|
|
|
global.ADD_TO_STAT("STOP_METHOD")
|
|
|
|
global.ADD_TO_STAT("STOP_METHOD:NO")
|
|
|
|
this.AddCheckErrCount(Node, 1)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (Param.Hot && !Node.Hot) {
|
|
|
|
this.AddCheckErrCount(Node, 1)
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (Param.Period && !Node.VersionOK && !Param.LowVersion) {
|
|
|
|
global.ADD_TO_STAT("STOP_METHOD")
|
|
|
|
global.ADD_TO_STAT("STOP_METHOD:LOWVERSION:" + Name)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (global.STOPGETBLOCK && Param.Hard === 2 && Node.BlockProcessCount < 1000000) {
|
|
|
|
Node.NextPing = 1 * 1000
|
|
|
|
global.ADD_TO_STAT("STOP_METHOD")
|
|
|
|
global.ADD_TO_STAT("STOP_METHOD:STOPGETBLOCK:" + Name)
|
|
|
|
this.AddCheckErrCount(Node, 0.5)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
var ArrTime = Node.TimeMap[Name];
|
|
|
|
if (!ArrTime) {
|
|
|
|
ArrTime = [0, 0, 0]
|
|
|
|
Node.TimeMap[Name] = ArrTime
|
|
|
|
}
|
|
|
|
ArrTime.sort(function(a, b) {
|
|
|
|
return a - b;
|
|
|
|
})
|
|
|
|
var Delta = CurTime - ArrTime[0];
|
|
|
|
if (Delta < Param.Period) {
|
|
|
|
global.ADD_TO_STAT("STOP_METHOD")
|
|
|
|
global.ADD_TO_STAT("STOP_METHOD:" + Name)
|
|
|
|
this.AddCheckErrCount(Node, 1)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
ArrTime[0] = CurTime
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
DoHardPacketForSend() {
|
|
|
|
global.ADD_TO_STAT("MAX:BUSY_LEVEL", this.BusyLevel)
|
|
|
|
global.ADD_TO_STAT("MAX:HARD_PACKET_SIZE", this.HardPacketForSend.size)
|
|
|
|
var Delta = Date.now() - this.LastTimeHard;
|
|
|
|
this.LastTimeHard = Date.now()
|
|
|
|
if (Delta > global.HARD_PACKET_PERIOD120 * HARD_PACKET_PERIOD / 100) {
|
|
|
|
global.ADD_TO_STAT("HARD_PACKET_PERIOD120")
|
|
|
|
var Delta2 = Date.now() - this.LastTimeHardOK;
|
|
|
|
if (Delta2 > 100) {
|
|
|
|
var Info = this.HardPacketForSend.min();
|
|
|
|
this.RiseBusyLevelByInfo(Info)
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (this.BusyLevel)
|
|
|
|
this.BusyLevel = this.BusyLevel / 1.1
|
|
|
|
this.LastTimeHardOK = Date.now()
|
|
|
|
global.ADD_TO_STAT("HARD_PACKET_PERIOD")
|
|
|
|
this.DoHardPacketForSendNext()
|
|
|
|
}
|
|
|
|
RiseBusyLevelByInfo(Info) {
|
|
|
|
if (!Info)
|
|
|
|
return;
|
|
|
|
if (!this.BusyLevel)
|
|
|
|
this.BusyLevel = 1
|
|
|
|
if (Info.BlockProcessCount > this.BusyLevel)
|
|
|
|
this.BusyLevel = Info.BlockProcessCount + 1
|
|
|
|
if (this.BusyLevel <= 0)
|
|
|
|
this.BusyLevel = 1
|
|
|
|
}
|
|
|
|
DropBusyLevelByInfo(Info) {
|
|
|
|
if (!Info)
|
|
|
|
return;
|
|
|
|
if (this.BusyLevel > Info.BlockProcessCount)
|
|
|
|
this.BusyLevel = Info.BlockProcessCount - 1
|
|
|
|
if (this.BusyLevel < 0)
|
|
|
|
this.BusyLevel = 0
|
|
|
|
}
|
|
|
|
DoHardPacketForSendNext() {
|
|
|
|
var Info = this.HardPacketForSend.min();
|
|
|
|
if (!Info) {
|
|
|
|
this.BusyLevel = 0
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.DropBusyLevelByInfo(Info)
|
|
|
|
this.HardPacketForSend.remove(Info)
|
|
|
|
this.OnPacketTCP(Info)
|
|
|
|
global.ADD_TO_STAT("DO_HARD_PACKET")
|
|
|
|
global.ADD_TO_STAT("DO_HARD_PACKET:" + Info.Method)
|
|
|
|
var DeltaTime = Date.now() - Info.TimeLoad;
|
2019-07-10 07:59:04 +00:00
|
|
|
if (this.HardPacketForSend.size && DeltaTime > global.PACKET_ALIVE_PERIOD / 2) {
|
2019-07-10 04:01:15 +00:00
|
|
|
global.ADD_TO_STAT("DELETE_HARD_PACKET_OLD", this.HardPacketForSend.size)
|
|
|
|
this.HardPacketForSend.clear()
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var MaxCount = 20;
|
|
|
|
while (Info = this.HardPacketForSend.max()) {
|
|
|
|
var DeltaTime = Date.now() - Info.TimeLoad;
|
2019-07-10 07:59:04 +00:00
|
|
|
if (DeltaTime > global.PACKET_ALIVE_PERIOD / 2 || !Info.Node.Socket || Info.Node.Socket.WasClose) {
|
2019-07-10 04:01:15 +00:00
|
|
|
this.HardPacketForSend.remove(Info)
|
2019-07-10 07:59:04 +00:00
|
|
|
if (DeltaTime > global.PACKET_ALIVE_PERIOD / 2) {
|
2019-07-10 04:01:15 +00:00
|
|
|
this.RiseBusyLevelByInfo(Info)
|
|
|
|
Info.Node.NextPing = 1 * 1000
|
|
|
|
this.AddCheckErrCount(Info.Node, 0.2)
|
|
|
|
global.ADD_TO_STAT("DELETE_HARD_PACKET_OLD")
|
|
|
|
global.ADD_TO_STAT("DELETE_HARD_PACKET_OLD:" + Info.Method)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
global.ADD_TO_STAT("DELETE_HARD_PACKET_NO_ALIVE")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MaxCount--
|
|
|
|
if (MaxCount <= 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Send(Node, Info, TypeData) {
|
|
|
|
if (!Node.Socket) {
|
|
|
|
this.DeleteNodeFromActive(Node)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (Info.Context) {
|
|
|
|
Info.ContextID = Info.Context.ContextID
|
|
|
|
if (!Info.ContextID) {
|
|
|
|
Info.ContextID = crypto.randomBytes(32)
|
|
|
|
Info.Context.ContextID = Info.ContextID
|
|
|
|
}
|
|
|
|
global.ContextPackets.SaveValue(Info.ContextID, Info.Context)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Info.ContextID = []
|
|
|
|
}
|
|
|
|
Node.SendPacketNum++
|
|
|
|
Info.Node = Node
|
|
|
|
Info.TypeData = TypeData
|
|
|
|
Info.Prioritet = Node.Prioritet
|
|
|
|
Info.PacketNum = Node.SendPacketNum
|
|
|
|
Info.TimeNum = Date.now()
|
|
|
|
Node.SendPacket.insert(Info)
|
|
|
|
}
|
|
|
|
DoSendPacketNodeAll(Node) {
|
|
|
|
while (this.DoSendPacketNode(Node) === 1);
|
|
|
|
}
|
|
|
|
DoSendPacketNode(Node) {
|
|
|
|
var TimeNum = Date.now();
|
|
|
|
var Info = Node.SendPacket.max();
|
2019-07-10 07:59:04 +00:00
|
|
|
if (Info && TimeNum - Info.TimeNum > global.PACKET_ALIVE_PERIOD)
|
2019-07-10 04:01:15 +00:00
|
|
|
while (Info = Node.SendPacket.max()) {
|
|
|
|
var DeltaTime = TimeNum - Info.TimeNum;
|
2019-07-10 07:59:04 +00:00
|
|
|
if (DeltaTime > global.PACKET_ALIVE_PERIOD / 2) {
|
2019-07-10 04:01:15 +00:00
|
|
|
Node.SendPacket.remove(Info)
|
|
|
|
global.ADD_TO_STAT("DELETE_OLD_PACKET")
|
|
|
|
}
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Info = Node.SendPacket.min()
|
|
|
|
if (!Info)
|
|
|
|
return 0;
|
2019-07-11 05:35:16 +00:00
|
|
|
global.ADD_TO_STAT("MAX:NODE_BUF_WRITE:" + global.NodeName(Node), Node.BufWrite.length / 1024, 1)
|
|
|
|
global.ADD_TO_STAT("MAX:NODE_SEND_BUF_PACKET_COUNT:" + global.NodeName(Node), Node.SendPacket.size, 1)
|
2019-07-10 04:01:15 +00:00
|
|
|
if (Node.BufWrite.length > 2 * TRAFIC_LIMIT_1S) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
Node.SendPacket.remove(Info)
|
|
|
|
if (Info.Context) {
|
|
|
|
if (!Info.Context.SendCount)
|
|
|
|
Info.Context.SendCount = 0
|
|
|
|
Info.Context.SendCount++
|
|
|
|
}
|
|
|
|
var BufWrite = this.GetBufFromData(Info.Method, Info.Data, Info.TypeData, Info.ContextID);
|
|
|
|
Node.BufWriteLength += BufWrite.length
|
|
|
|
if (Node.BufWrite.length === 0)
|
|
|
|
Node.BufWrite = BufWrite
|
|
|
|
else
|
|
|
|
Node.BufWrite = Buffer.concat([Node.BufWrite, BufWrite])
|
|
|
|
global.ADD_TO_STAT("SEND:" + Info.Method)
|
|
|
|
global.ADD_TO_STAT("SEND:(KB)" + Info.Method, BufWrite.length / 1024)
|
2019-07-11 05:35:16 +00:00
|
|
|
global.ADD_TO_STAT("SEND:" + Info.Method + ":" + global.NodeName(Node), 1, 1)
|
|
|
|
global.TO_DEBUG_LOG("SEND " + Info.Method + " to " + global.NodeInfo(Node) + " LENGTH=" + BufWrite.length)
|
2019-07-10 04:01:15 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
DoSendPacket() {
|
|
|
|
var it = this.ActualNodes.iterator(), Node;
|
|
|
|
while ((Node = it.next()) !== null)
|
|
|
|
if (Node.ConnectStatus() === 100) {
|
|
|
|
this.DoSendPacketNode(Node)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
global.ADD_TO_STAT("SEND_ERROR")
|
|
|
|
this.AddCheckErrCount(Node, 0.005, "NODE STATUS=" + Node.ConnectStatus())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DoSendBuf() {
|
|
|
|
this.RecalcSendStatictic()
|
2019-07-11 07:52:17 +00:00
|
|
|
var CountNodeSend = 0;
|
2019-07-10 04:01:15 +00:00
|
|
|
var it = this.ActualNodes.iterator(), Node;
|
|
|
|
NEXT_NODE:
|
|
|
|
while ((Node = it.next()) !== null)
|
|
|
|
if (Node.Socket && Node.ConnectStatus() === 100)
|
|
|
|
if (Node.BufWrite.length > 0) {
|
2019-07-11 07:52:17 +00:00
|
|
|
CountNodeSend++
|
2019-07-10 04:01:15 +00:00
|
|
|
var CountSend = Math.min(BUF_PACKET_SIZE, Node.BufWrite.length);
|
|
|
|
var Value = CountSend / 1024;
|
|
|
|
if (global.LIMIT_SEND_TRAFIC) {
|
|
|
|
var CanCountSend = Node.SendTrafficLimit - Node.SendTrafficCurrent;
|
|
|
|
if (CanCountSend < CountSend) {
|
|
|
|
if (this.SendTrafficFree < CountSend) {
|
2019-07-11 05:35:16 +00:00
|
|
|
global.ADD_TO_STAT("LIMIT_SENDDATA:" + global.NodeName(Node), Value, 1)
|
2019-07-10 04:01:15 +00:00
|
|
|
continue NEXT_NODE;
|
|
|
|
}
|
|
|
|
this.SendTrafficFree -= CountSend
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Node.write(Node.BufWrite.slice(0, CountSend))
|
|
|
|
Node.SendTrafficCurrent += CountSend
|
|
|
|
Node.BufWrite = Node.BufWrite.slice(CountSend)
|
|
|
|
this.ADD_CURRENT_STAT_TIME("SEND_DATA", Value)
|
|
|
|
global.ADD_TO_STAT("SENDDATA(KB)", Value)
|
2019-07-11 05:35:16 +00:00
|
|
|
global.ADD_TO_STAT("SENDDATA(KB):" + global.NodeName(Node), Value, 1)
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
CheckPOWTicketConnect(Socket, data) {
|
|
|
|
try {
|
2019-07-10 07:59:04 +00:00
|
|
|
var Info = global.BufLib.GetObjectFromBuffer(data, global.FORMAT_POW_TO_SERVER, {});
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
this.SendCloseSocket(Socket, "FORMAT_POW_TO_SERVER")
|
|
|
|
return;
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
if (Info.DEF_NETWORK !== global.GetNetworkName()) {
|
|
|
|
this.SendCloseSocket(Socket, "DEF_NETWORK=" + Info.DEF_NETWORK + " MUST:" + global.GetNetworkName())
|
2019-07-10 04:01:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
var Node = this.FindRunNodeContext(Info.addrArr, Info.FromIP, Info.FromPort, true);
|
|
|
|
if (global.CompareArr(Info.addrArr, this.addrArr) === 0) {
|
2019-07-10 07:59:04 +00:00
|
|
|
global.AddNodeInfo(Node, "SERV: GET SELF")
|
2019-07-10 04:01:15 +00:00
|
|
|
this.SendCloseSocket(Socket, "SELF")
|
|
|
|
return;
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
var Hash = global.shaarr2(this.addrArr, Socket.HashRND);
|
|
|
|
var hashInfo = global.GetHashWithValues(Hash, Info.nonce, 0);
|
|
|
|
var power = global.GetPowPower(hashInfo);
|
2019-07-10 04:01:15 +00:00
|
|
|
if (Info.Reconnect) {
|
|
|
|
if ((Node.SecretForReconnect && Node.WaitConnectFromServer && global.CompareArr(Node.SecretForReconnect, Info.SecretForReconnect) === 0) || Info.Reconnect === 255) {
|
2019-07-10 07:59:04 +00:00
|
|
|
let Result = 1;
|
2019-07-10 04:01:15 +00:00
|
|
|
if (Info.Reconnect === 255) {
|
2019-07-10 07:59:04 +00:00
|
|
|
Result = global.CheckDevelopSign(Hash, Info.Sign)
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
|
|
|
if (Result) {
|
|
|
|
Node.NextConnectDelta = 1000
|
|
|
|
Node.WaitConnectFromServer = 0
|
|
|
|
Node.GrayConnect = 0
|
2019-07-11 05:35:16 +00:00
|
|
|
global.AddNodeInfo(Node, "3. SERVER OK CONNECT for client node " + global.SocketInfo(Socket))
|
2019-07-10 04:01:15 +00:00
|
|
|
this.AddNodeToActive(Node)
|
|
|
|
Node.Socket = Socket
|
2019-07-11 05:35:16 +00:00
|
|
|
global.SetSocketStatus(Socket, 3)
|
|
|
|
global.SetSocketStatus(Socket, 100)
|
2019-07-10 04:01:15 +00:00
|
|
|
Socket.Node = Node
|
|
|
|
Socket.write(this.GetBufFromData("POW_CONNECT0", "OK", 2))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Node.NextConnectDelta = 60 * 1000
|
2019-07-11 05:35:16 +00:00
|
|
|
global.ToLog("Error Sign Node from " + global.NodeInfo(Node))
|
2019-07-10 04:01:15 +00:00
|
|
|
this.AddCheckErrCount(Node, 10, "Error Sign Node")
|
|
|
|
}
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
global.AddNodeInfo(Node, "SERV: ERROR_RECONNECT")
|
2019-07-10 04:01:15 +00:00
|
|
|
Socket.end(this.GetBufFromData("POW_CONNEC11", "ERROR_RECONNECT", 2))
|
2019-07-10 07:59:04 +00:00
|
|
|
global.CloseSocket(Socket, "ERROR_RECONNECT")
|
2019-07-10 04:01:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
2019-07-10 07:59:04 +00:00
|
|
|
if (power < global.MIN_POWER_POW_HANDSHAKE) {
|
2019-07-10 04:01:15 +00:00
|
|
|
global.ToLog("END: MIN_POWER_POW_HANDSHAKE")
|
2019-07-10 07:59:04 +00:00
|
|
|
global.AddNodeInfo(Node, "SERV: ERR MIN_POWER_POW_HANDSHAKE")
|
2019-07-10 04:01:15 +00:00
|
|
|
Socket.end(this.GetBufFromData("POW_CONNECT2", "MIN_POWER_POW_HANDSHAKE", 2))
|
2019-07-10 07:59:04 +00:00
|
|
|
global.CloseSocket(Socket, "MIN_POWER_POW_HANDSHAKE")
|
2019-07-10 04:01:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!Node.BlockProcessCount)
|
|
|
|
Node.BlockProcessCount = 0
|
2019-07-10 07:59:04 +00:00
|
|
|
if (this.ActualNodes.size >= global.MAX_CONNECTIONS_COUNT && Node.BlockProcessCount < global.TRUST_PROCESS_COUNT) {
|
|
|
|
global.AddNodeInfo(Node, "SERV: ERROR_MAX_CLIENTS")
|
2019-07-10 04:01:15 +00:00
|
|
|
Socket.end(this.GetBufFromData("POW_CONNECT8", "ERROR_MAX_CLIENTS", 2))
|
2019-07-10 07:59:04 +00:00
|
|
|
global.CloseSocket(Socket, "ERROR_MAX_CLIENTS")
|
2019-07-10 04:01:15 +00:00
|
|
|
return;
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
let Result = false;
|
2019-07-10 04:01:15 +00:00
|
|
|
if (Info.PubKeyType === 2 || Info.PubKeyType === 3)
|
2019-07-11 07:52:17 +00:00
|
|
|
Result = secp256k1.verify(Buffer.from(Hash), Buffer.from(Info.Sign), Buffer.from([Info.PubKeyType].concat(Info.addrArr)))
|
2019-07-10 04:01:15 +00:00
|
|
|
if (!Result) {
|
2019-07-10 07:59:04 +00:00
|
|
|
global.AddNodeInfo(Node, "SERV: ERROR_SIGN_CLIENT")
|
2019-07-10 04:01:15 +00:00
|
|
|
Socket.end(this.GetBufFromData("POW_CONNECT8", "ERROR_SIGN_CLIENT", 2))
|
2019-07-10 07:59:04 +00:00
|
|
|
global.CloseSocket(Socket, "ERROR_SIGN_CLIENT")
|
2019-07-10 04:01:15 +00:00
|
|
|
this.AddToBanIP(Socket.remoteAddress, "ERROR_SIGN_CLIENT")
|
|
|
|
return;
|
|
|
|
}
|
2019-07-11 05:35:16 +00:00
|
|
|
global.AddNodeInfo(Node, "1. SERVER OK POW for client node " + global.SocketInfo(Socket))
|
2019-07-10 04:01:15 +00:00
|
|
|
Node.FromIP = Info.FromIP
|
|
|
|
Node.FromPort = Info.FromPort
|
|
|
|
Node.SecretForReconnect = crypto.randomBytes(20)
|
|
|
|
Node.PubKey = Buffer.from([Info.PubKeyType].concat(Info.addrArr))
|
|
|
|
if (Info.GrayConnect) {
|
|
|
|
Node.NextConnectDelta = 1000
|
|
|
|
Node.WaitConnectFromServer = 0
|
|
|
|
Node.GrayConnect = 1
|
2019-07-11 05:35:16 +00:00
|
|
|
global.AddNodeInfo(Node, "5. CLIENT OK GRAY CONNECT " + global.SocketInfo(Socket))
|
2019-07-10 04:01:15 +00:00
|
|
|
this.AddNodeToActive(Node)
|
|
|
|
Node.Socket = Socket
|
2019-07-11 05:35:16 +00:00
|
|
|
global.SetSocketStatus(Socket, 3)
|
|
|
|
global.SetSocketStatus(Socket, 100)
|
2019-07-10 04:01:15 +00:00
|
|
|
Socket.Node = Node
|
|
|
|
Socket.write(this.GetBufFromData("POW_CONNECT0", "OK", 2))
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!Node.WasAddToReconnect) {
|
|
|
|
Node.WasAddToReconnect = 1
|
|
|
|
Node.ReconnectFromServer = 1
|
|
|
|
global.ArrReconnect.push(Node)
|
|
|
|
}
|
|
|
|
Socket.write(this.GetBufFromData("POW_CONNECT4", "WAIT_CONNECT_FROM_SERVER:" + global.GetHexFromArr(Node.SecretForReconnect), 2))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StopServer() {
|
|
|
|
if (this.Server)
|
|
|
|
this.Server.close()
|
|
|
|
}
|
|
|
|
StartServer() {
|
2019-07-10 07:59:04 +00:00
|
|
|
if (global.GrayConnect()) {
|
2019-07-10 04:01:15 +00:00
|
|
|
this.CanSend++
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
let SELF = this;
|
2019-07-10 09:28:08 +00:00
|
|
|
this.Server = net.createServer(function(sock: any) {
|
2019-07-10 04:01:15 +00:00
|
|
|
if (SELF.WasBanIP({ address: sock.remoteAddress })) {
|
|
|
|
sock.ConnectID = "new"
|
2019-07-10 07:59:04 +00:00
|
|
|
global.CloseSocket(sock, "WAS BAN", true)
|
2019-07-10 04:01:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
let SOCKET = sock;
|
2019-07-10 07:59:04 +00:00
|
|
|
global.socketInit(SOCKET, "c")
|
2019-07-11 05:35:16 +00:00
|
|
|
global.SetSocketStatus(SOCKET, 0)
|
2019-07-10 07:59:04 +00:00
|
|
|
global.AddNodeInfo(SOCKET, "Client *" + SOCKET.ConnectID + " connected from " + SOCKET.remoteAddress + ":" + SOCKET.remotePort, 1)
|
2019-07-10 04:01:15 +00:00
|
|
|
global.ADD_TO_STAT("ClientConnected")
|
|
|
|
SOCKET.HashRND = crypto.randomBytes(32)
|
|
|
|
var Data = {
|
2019-07-10 07:59:04 +00:00
|
|
|
addrArr: SELF.addrArr, HashRND: SOCKET.HashRND, MIN_POWER_POW_HANDSHAKE: global.MIN_POWER_POW_HANDSHAKE, PubKeyType: SELF.PubKeyType,
|
2019-07-10 04:01:15 +00:00
|
|
|
Sign: SELF.ServerSign, Reserve: []
|
|
|
|
};
|
2019-07-10 07:59:04 +00:00
|
|
|
var BufData = global.BufLib.GetBufferFromObject(Data, global.FORMAT_POW_TO_CLIENT, 300, {});
|
2019-07-10 04:01:15 +00:00
|
|
|
var BufWrite = SELF.GetBufFromData("POW_CONNECT5", BufData, 1);
|
|
|
|
try {
|
|
|
|
SOCKET.write(BufWrite)
|
|
|
|
}
|
|
|
|
catch (e) {
|
|
|
|
global.ToError(e)
|
|
|
|
SOCKET = undefined
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
SOCKET.on('data', function(data) {
|
|
|
|
if (SOCKET.WasClose) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!SOCKET.Node) {
|
|
|
|
var Buf = SELF.GetDataFromBuf(data);
|
|
|
|
if (Buf) {
|
|
|
|
SELF.CheckPOWTicketConnect(SOCKET, Buf.Data)
|
|
|
|
SOCKET.ConnectToServer = 0
|
|
|
|
return;
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
global.CloseSocket(SOCKET, "=SERVER ON DATA=")
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
|
|
|
else {
|
2019-07-10 07:59:04 +00:00
|
|
|
global.socketRead(SOCKET, data)
|
2019-07-10 04:01:15 +00:00
|
|
|
SELF.OnGetFromTCP(SOCKET.Node, SOCKET, data)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
SOCKET.on('end', function() {
|
|
|
|
global.ADD_TO_STAT("ClientEnd")
|
|
|
|
var Node = SOCKET.Node;
|
2019-07-11 05:35:16 +00:00
|
|
|
var Status = global.GetSocketStatus(SOCKET);
|
2019-07-10 04:01:15 +00:00
|
|
|
if (Status)
|
2019-07-11 05:35:16 +00:00
|
|
|
global.AddNodeInfo(Node, "Get socket end *" + SOCKET.ConnectID + " from client Stat: " + global.SocketStatistic(SOCKET))
|
2019-07-10 04:01:15 +00:00
|
|
|
if (Node && Status === 200) {
|
|
|
|
Node.SwapSockets()
|
|
|
|
SOCKET.WasClose = 1
|
|
|
|
}
|
|
|
|
})
|
|
|
|
SOCKET.on('close', function(err) {
|
|
|
|
global.ADD_TO_STAT("ClientClose")
|
2019-07-11 05:35:16 +00:00
|
|
|
if (SOCKET.ConnectID && global.GetSocketStatus(SOCKET))
|
|
|
|
global.AddNodeInfo(SOCKET.Node, "Get socket close *" + SOCKET.ConnectID + " from client Stat: " + global.SocketStatistic(SOCKET))
|
2019-07-10 04:01:15 +00:00
|
|
|
if (!SOCKET.WasClose && SOCKET.Node) {
|
2019-07-10 07:59:04 +00:00
|
|
|
global.CloseSocket(SOCKET, "GET CLOSE")
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
2019-07-11 05:35:16 +00:00
|
|
|
global.SetSocketStatus(SOCKET, 0)
|
2019-07-10 04:01:15 +00:00
|
|
|
})
|
|
|
|
SOCKET.on('error', function(err) {
|
|
|
|
global.ADD_TO_STAT("ERRORS")
|
2019-07-10 07:59:04 +00:00
|
|
|
global.CloseSocket(SOCKET, "ERRORS")
|
2019-07-10 04:01:15 +00:00
|
|
|
if (SOCKET.Node)
|
|
|
|
SELF.AddCheckErrCount(SOCKET.Node, 1, "ERR##2 : socket")
|
|
|
|
})
|
|
|
|
})
|
|
|
|
this.Server.on('close', function() {
|
|
|
|
})
|
|
|
|
this.Server.on('error', function(err) {
|
|
|
|
if (err.code === 'EADDRINUSE') {
|
2019-07-10 07:59:04 +00:00
|
|
|
global.ToLogClient('Port ' + SELF.port + ' in use, retrying...')
|
2019-07-10 04:01:15 +00:00
|
|
|
if (SELF.Server)
|
|
|
|
SELF.Server.close()
|
|
|
|
setTimeout(function() {
|
|
|
|
SELF.RunListenServer()
|
|
|
|
}, 5000)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
global.ADD_TO_STAT("ERRORS")
|
|
|
|
global.ToError("ERR##3")
|
|
|
|
})
|
|
|
|
if (!SELF.ip) {
|
|
|
|
this.FindInternetIP()
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
this.CanSend++
|
|
|
|
this.RunListenServer()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
RunListenServer() {
|
2019-07-10 07:59:04 +00:00
|
|
|
if (!global.START_PORT_NUMBER || global.START_PORT_NUMBER === "undefined")
|
|
|
|
global.START_PORT_NUMBER = 30000
|
2019-07-10 04:01:15 +00:00
|
|
|
let SELF = this;
|
2019-07-10 07:59:04 +00:00
|
|
|
SELF.port = global.START_PORT_NUMBER
|
|
|
|
global.ToLogClient("Prepare to run TCP server on " + global.LISTEN_IP + ":" + SELF.port)
|
|
|
|
this.Server.listen(SELF.port, global.LISTEN_IP, function() {
|
2019-07-10 04:01:15 +00:00
|
|
|
if (SELF.CanSend < 2)
|
2019-07-10 07:59:04 +00:00
|
|
|
global.ToLogClient("Run TCP server on " + SELF.ip + ":" + SELF.port)
|
2019-07-10 04:01:15 +00:00
|
|
|
SELF.CanSend++
|
2019-07-11 07:52:17 +00:00
|
|
|
var Hash = global.sha3(SELF.addrStr)
|
|
|
|
SELF.ServerSign = secp256k1.sign(Buffer.from(Hash), SELF.KeyPair.getPrivateKey('')).signature
|
2019-07-10 04:01:15 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
FindInternetIP() {
|
2019-07-10 07:59:04 +00:00
|
|
|
let Stun = global.Stun;
|
2019-07-10 04:01:15 +00:00
|
|
|
let SELF = this;
|
|
|
|
let server = Stun.createServer();
|
|
|
|
const request = Stun.createMessage(Stun.constants.STUN_BINDING_REQUEST);
|
|
|
|
server.on('error', function(err) {
|
|
|
|
SELF.CanSend++
|
|
|
|
})
|
|
|
|
server.once('bindingResponse', function(stunMsg) {
|
|
|
|
var value = stunMsg.getAttribute(Stun.constants.STUN_ATTR_XOR_MAPPED_ADDRESS).value;
|
|
|
|
global.ToLog("INTERNET IP:" + value.address)
|
|
|
|
SELF.CanSend++
|
|
|
|
global.INTERNET_IP_FROM_STUN = value.address
|
|
|
|
if (!SELF.ip)
|
2019-07-10 07:59:04 +00:00
|
|
|
SELF.ip = global.INTERNET_IP_FROM_STUN
|
2019-07-10 04:01:15 +00:00
|
|
|
if (server)
|
|
|
|
server.close()
|
|
|
|
SELF.RunListenServer()
|
|
|
|
})
|
|
|
|
var StrStunAddr = 'stun.l.google.com';
|
|
|
|
const dns = require('dns');
|
|
|
|
dns.lookup(StrStunAddr, function(err, address, family) {
|
|
|
|
if (!err)
|
|
|
|
server.send(request, 19302, StrStunAddr)
|
|
|
|
else
|
|
|
|
SELF.CanSend++
|
|
|
|
})
|
|
|
|
}
|
|
|
|
CLOSE_SOCKET(Context, CurTime) {
|
2019-07-10 07:59:04 +00:00
|
|
|
global.AddNodeInfo(Context.Socket.Node, "GET CLOSE_SOCKET *" + Context.Socket.ConnectID + ": " + Context.Data.toString())
|
|
|
|
global.CloseSocket(Context.Socket, "CLOSE_SOCKET")
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
|
|
|
SendCloseSocket(Socket, Str) {
|
2019-07-11 05:35:16 +00:00
|
|
|
global.AddNodeInfo(Socket.Node, "CLOSE_SOCKET " + global.SocketInfo(Socket) + " - " + Str)
|
2019-07-10 04:01:15 +00:00
|
|
|
if (Socket.WasClose) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.AddCheckErrCount(Socket.Node, 1, "SendCloseSocket")
|
|
|
|
if (Socket.Node && Socket.Node.BufWrite && Socket.Node.BufWrite.length > 0) {
|
|
|
|
}
|
|
|
|
else {
|
2019-07-10 07:59:04 +00:00
|
|
|
global.AddNodeInfo(Socket.Node, "END *" + Socket.ConnectID + ": " + Str)
|
2019-07-10 04:01:15 +00:00
|
|
|
Socket.end(this.GetBufFromData("CLOSE_SOCKET", Str, 2))
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
global.CloseSocket(Socket, Str)
|
2019-07-10 04:01:15 +00:00
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
AddCheckErrCount(Node, Count, StrErr?) {
|
2019-07-10 04:01:15 +00:00
|
|
|
if (!Node)
|
|
|
|
return;
|
|
|
|
if (!Count)
|
|
|
|
Count = 1
|
|
|
|
var Delta = Date.now() - Node.LastTimeError;
|
|
|
|
if (Delta > 10 * 1000) {
|
|
|
|
Node.ErrCount = 0
|
|
|
|
}
|
|
|
|
Node.LastTimeError = Date.now()
|
|
|
|
Node.ErrCountAll += Count
|
|
|
|
Node.ErrCount += Count
|
|
|
|
if (Node.ErrCount >= 5) {
|
|
|
|
Node.ErrCount = 0
|
|
|
|
global.ADD_TO_STAT("ERRORS")
|
|
|
|
Node.BlockProcessCount--
|
|
|
|
if (Node.BlockProcessCount < - 30) {
|
|
|
|
if (!StrErr)
|
|
|
|
StrErr = ""
|
|
|
|
this.AddToBan(Node, StrErr + " BlockProcess:" + Node.BlockProcessCount)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2019-07-13 02:22:28 +00:00
|
|
|
global.ContextPackets = new STreeBuffer(10 * 1000, global.CompareItemHash32, "object");
|
2019-07-10 04:01:15 +00:00
|
|
|
|
|
|
|
function CalcStatArr(arr, arrAvg, arrNext, Period) {
|
|
|
|
var arrSum = [arr[0]];
|
|
|
|
for (var i = 1; i < arr.length; i++) {
|
|
|
|
arrSum[i] = arrSum[i - 1] + arr[i];
|
|
|
|
}
|
|
|
|
for (var i = 0; i < arrSum.length; i++) {
|
|
|
|
if (i < Period)
|
|
|
|
arrAvg[i] = Math.floor(arrSum[i] / (i + 1));
|
|
|
|
else {
|
|
|
|
arrAvg[i] = Math.floor((arrSum[i] - arrSum[i - Period]) / Period);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
arrNext[0] = 0;
|
|
|
|
for (var i = 1; i < arrAvg.length; i++) {
|
|
|
|
var Avg = arrSum[i] / (i + 1);
|
|
|
|
var minValue = Avg / 20;
|
|
|
|
var Value1 = arrAvg[i - 1];
|
|
|
|
var Value2 = arrAvg[i];
|
|
|
|
if (Value1 < minValue)
|
|
|
|
Value1 = minValue;
|
|
|
|
if (Value2 < minValue)
|
|
|
|
Value2 = minValue;
|
|
|
|
var KLast = Math.floor(100 * (Value2 - Value1) / Value1) / 100;
|
|
|
|
var AvgLast = arrAvg[i];
|
|
|
|
if (Avg > AvgLast)
|
|
|
|
AvgLast = Avg;
|
|
|
|
if (KLast > 2.0)
|
|
|
|
KLast = 2.0;
|
|
|
|
if (KLast < - 0.0)
|
|
|
|
KLast = - 0.0;
|
|
|
|
arrNext[i] = AvgLast * (1 + KLast);
|
|
|
|
var AvgMax = 0;
|
|
|
|
if (0)
|
|
|
|
if (i > 1 * Period) {
|
|
|
|
for (var j = i - Period / 2; j <= i; j++)
|
|
|
|
if (arrAvg[j] > AvgMax)
|
|
|
|
AvgMax = arrAvg[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return arrNext[arrNext.length - 1];
|
|
|
|
};
|