1.5.5
This commit is contained in:
+275
-92
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
type P2PTunnel struct {
|
||||
pn *P2PNetwork
|
||||
conn p2pConn
|
||||
conn underlay
|
||||
hbTime time.Time
|
||||
hbMtx sync.Mutex
|
||||
hbTimeRelay time.Time
|
||||
@@ -25,7 +25,7 @@ type P2PTunnel struct {
|
||||
id uint64
|
||||
running bool
|
||||
runMtx sync.Mutex
|
||||
isServer bool // 0:server 1:client
|
||||
tunnelServer bool // different from underlayServer
|
||||
coneLocalPort int
|
||||
coneNatPort int
|
||||
}
|
||||
@@ -39,29 +39,47 @@ func (t *P2PTunnel) init() {
|
||||
localPort := int(rand.Uint32()%10000 + 50000)
|
||||
if t.pn.config.natType == NATCone {
|
||||
// prepare one random cone hole
|
||||
_, _, port1, _ := natTest(t.pn.config.ServerHost, t.pn.config.UDPPort1, localPort, 0)
|
||||
_, _, _, port1, _ := natTest(t.pn.config.ServerHost, t.pn.config.UDPPort1, localPort, 0)
|
||||
t.coneLocalPort = localPort
|
||||
t.coneNatPort = port1
|
||||
t.la = &net.UDPAddr{IP: net.ParseIP(t.pn.config.localIP), Port: t.coneLocalPort}
|
||||
} else {
|
||||
t.coneLocalPort = localPort
|
||||
t.coneNatPort = localPort // NATNONE or symmetric doesn't need coneNatPort
|
||||
t.coneNatPort = localPort // symmetric doesn't need coneNatPort
|
||||
if t.pn.config.hasUPNPorNATPMP == 1 {
|
||||
nat, err := Discover()
|
||||
if err != nil {
|
||||
gLog.Println(LvDEBUG, "could not perform UPNP discover:", err)
|
||||
} else {
|
||||
externalPort, err := nat.AddPortMapping("tcp", localPort, localPort, "openp2p", 30) // timeout the connection still alive, make the timeout short
|
||||
if err != nil {
|
||||
gLog.Println(LvDEBUG, "could not add udp UPNP port mapping", externalPort)
|
||||
}
|
||||
}
|
||||
}
|
||||
t.la = &net.UDPAddr{IP: net.ParseIP(t.pn.config.localIP), Port: t.coneLocalPort}
|
||||
}
|
||||
gLog.Printf(LevelDEBUG, "prepare punching port %d:%d", t.coneLocalPort, t.coneNatPort)
|
||||
gLog.Printf(LvDEBUG, "prepare punching port %d:%d", t.coneLocalPort, t.coneNatPort)
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) connect() error {
|
||||
gLog.Printf(LevelDEBUG, "start p2pTunnel to %s ", t.config.PeerNode)
|
||||
t.isServer = false
|
||||
gLog.Printf(LvDEBUG, "start p2pTunnel to %s ", t.config.PeerNode)
|
||||
t.tunnelServer = false
|
||||
appKey := uint64(0)
|
||||
req := PushConnectReq{
|
||||
Token: t.config.peerToken,
|
||||
From: t.pn.config.Node,
|
||||
FromToken: t.pn.config.Token,
|
||||
FromIP: t.pn.config.publicIP,
|
||||
ConeNatPort: t.coneNatPort,
|
||||
NatType: t.pn.config.natType,
|
||||
ID: t.id}
|
||||
Token: t.config.peerToken,
|
||||
From: t.pn.config.Node,
|
||||
FromToken: t.pn.config.Token,
|
||||
FromIP: t.pn.config.publicIP,
|
||||
ConeNatPort: t.coneNatPort,
|
||||
NatType: t.pn.config.natType,
|
||||
HasIPv4: t.pn.config.hasIPv4,
|
||||
IPv6: t.pn.config.IPv6,
|
||||
HasUPNPorNATPMP: t.pn.config.hasUPNPorNATPMP,
|
||||
ID: t.id,
|
||||
AppKey: appKey,
|
||||
Version: OpenP2PVersion,
|
||||
}
|
||||
t.pn.push(t.config.PeerNode, MsgPushConnectReq, req)
|
||||
head, body := t.pn.read(t.config.PeerNode, MsgPush, MsgPushConnectRsp, time.Second*10)
|
||||
if head == nil {
|
||||
@@ -70,19 +88,23 @@ func (t *P2PTunnel) connect() error {
|
||||
rsp := PushConnectRsp{}
|
||||
err := json.Unmarshal(body, &rsp)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "wrong MsgPushConnectRsp:%s", err)
|
||||
gLog.Printf(LvERROR, "wrong MsgPushConnectRsp:%s", err)
|
||||
return err
|
||||
}
|
||||
// gLog.Println(LevelINFO, rsp)
|
||||
if rsp.Error != 0 {
|
||||
return errors.New(rsp.Detail)
|
||||
}
|
||||
t.config.peerNatType = int(rsp.NatType)
|
||||
t.config.peerNatType = rsp.NatType
|
||||
t.config.hasIPv4 = rsp.HasIPv4
|
||||
t.config.IPv6 = rsp.IPv6
|
||||
t.config.hasUPNPorNATPMP = rsp.HasUPNPorNATPMP
|
||||
t.config.peerVersion = rsp.Version
|
||||
t.config.peerConeNatPort = rsp.ConeNatPort
|
||||
t.config.peerIP = rsp.FromIP
|
||||
err = t.handshake()
|
||||
err = t.start()
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "handshake error:", err)
|
||||
gLog.Println(LvERROR, "handshake error:", err)
|
||||
err = ErrorHandshake
|
||||
}
|
||||
return err
|
||||
@@ -135,6 +157,20 @@ func (t *P2PTunnel) close() {
|
||||
t.pn.allTunnels.Delete(t.id)
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) start() error {
|
||||
if !t.isSupportTCP() {
|
||||
if err := t.handshake(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
err := t.connectUnderlay()
|
||||
if err != nil {
|
||||
gLog.Println(LvERROR, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) handshake() error {
|
||||
if t.config.peerConeNatPort > 0 {
|
||||
var err error
|
||||
@@ -143,7 +179,7 @@ func (t *P2PTunnel) handshake() error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
gLog.Println(LevelDEBUG, "handshake to ", t.config.PeerNode)
|
||||
gLog.Println(LvDEBUG, "handshake to ", t.config.PeerNode)
|
||||
var err error
|
||||
// TODO: handle NATNone, nodes with public ip has no punching
|
||||
if (t.pn.config.natType == NATCone && t.config.peerNatType == NATCone) || (t.pn.config.natType == NATNone || t.config.peerNatType == NATNone) {
|
||||
@@ -159,50 +195,70 @@ func (t *P2PTunnel) handshake() error {
|
||||
return errors.New("unknown error")
|
||||
}
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "punch handshake error:", err)
|
||||
return err
|
||||
}
|
||||
gLog.Printf(LevelDEBUG, "handshake to %s ok", t.config.PeerNode)
|
||||
err = t.run()
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, err)
|
||||
gLog.Println(LvERROR, "punch handshake error:", err)
|
||||
return err
|
||||
}
|
||||
gLog.Printf(LvDEBUG, "handshake to %s ok", t.config.PeerNode)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) run() error {
|
||||
if t.isServer {
|
||||
qConn, e := listenQuic(t.la.String(), TunnelIdleTimeout)
|
||||
if e != nil {
|
||||
gLog.Println(LevelINFO, "listen quic error:", e, ", retry...")
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
qConn, e = listenQuic(t.la.String(), TunnelIdleTimeout)
|
||||
if e != nil {
|
||||
return fmt.Errorf("listen quic error:%s", e)
|
||||
}
|
||||
func (t *P2PTunnel) connectUnderlay() (err error) {
|
||||
if !t.isSupportTCP() {
|
||||
t.conn, err = t.connectUnderlayQuic()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
t.pn.push(t.config.PeerNode, MsgPushQuicConnect, nil)
|
||||
e = qConn.Accept()
|
||||
if e != nil {
|
||||
} else {
|
||||
// TODO: udp or tcp first?
|
||||
// prepare a la ra for udp
|
||||
// t.conn, err = t.connectUnderlayQuic()
|
||||
// TODO: support ipv6
|
||||
// if t.pn.config.hasIPv4 == 1 || t.config.hasIPv4 == 1 {
|
||||
t.conn, err = t.connectUnderlayTCP()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// }
|
||||
// if IsIPv6(t.pn.config.IPv6) && IsIPv6(t.config.IPv6) { // both have ipv6
|
||||
// t.conn, err = t.connectUnderlayTCP6()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
// }
|
||||
}
|
||||
t.setRun(true)
|
||||
go t.readLoop()
|
||||
go t.heartbeatLoop()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) connectUnderlayQuic() (c underlay, err error) {
|
||||
gLog.Println(LvINFO, "connectUnderlayQuic start")
|
||||
defer gLog.Println(LvINFO, "connectUnderlayQuic end")
|
||||
var qConn *underlayQUIC
|
||||
if t.isUnderlayServer() {
|
||||
time.Sleep(time.Millisecond * 10) // punching udp port will need some times in some env
|
||||
qConn, err = listenQuic(t.la.String(), TunnelIdleTimeout)
|
||||
if err != nil {
|
||||
gLog.Println(LvINFO, "listen quic error:", err, ", retry...")
|
||||
}
|
||||
t.pn.push(t.config.PeerNode, MsgPushUnderlayConnect, nil)
|
||||
err = qConn.Accept()
|
||||
if err != nil {
|
||||
qConn.CloseListener()
|
||||
return fmt.Errorf("accept quic error:%s", e)
|
||||
return nil, fmt.Errorf("accept quic error:%s", err)
|
||||
}
|
||||
_, buff, err := qConn.ReadMessage()
|
||||
if e != nil {
|
||||
_, buff, err := qConn.ReadBuffer()
|
||||
if err != nil {
|
||||
qConn.listener.Close()
|
||||
return fmt.Errorf("read start msg error:%s", err)
|
||||
return nil, fmt.Errorf("read start msg error:%s", err)
|
||||
}
|
||||
if buff != nil {
|
||||
gLog.Println(LevelDEBUG, string(buff))
|
||||
gLog.Println(LvDEBUG, string(buff))
|
||||
}
|
||||
qConn.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, []byte("OpenP2P,hello2"))
|
||||
gLog.Println(LevelDEBUG, "quic connection ok")
|
||||
t.conn = qConn
|
||||
t.setRun(true)
|
||||
go t.readLoop()
|
||||
go t.writeLoop()
|
||||
return nil
|
||||
gLog.Println(LvDEBUG, "quic connection ok")
|
||||
return qConn, nil
|
||||
}
|
||||
|
||||
//else
|
||||
@@ -211,44 +267,133 @@ func (t *P2PTunnel) run() error {
|
||||
time.Sleep(time.Millisecond * 10)
|
||||
conn, e = net.ListenUDP("udp", t.la)
|
||||
if e != nil {
|
||||
return fmt.Errorf("quic listen error:%s", e)
|
||||
return nil, fmt.Errorf("quic listen error:%s", e)
|
||||
}
|
||||
}
|
||||
t.pn.read(t.config.PeerNode, MsgPush, MsgPushQuicConnect, time.Second*5)
|
||||
gLog.Println(LevelDEBUG, "quic dial to ", t.ra.String())
|
||||
qConn, e := dialQuic(conn, t.ra, TunnelIdleTimeout)
|
||||
t.pn.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, time.Second*5)
|
||||
gLog.Println(LvDEBUG, "quic dial to ", t.ra.String())
|
||||
qConn, e = dialQuic(conn, t.ra, TunnelIdleTimeout)
|
||||
if e != nil {
|
||||
return fmt.Errorf("quic dial to %s error:%s", t.ra.String(), e)
|
||||
return nil, fmt.Errorf("quic dial to %s error:%s", t.ra.String(), e)
|
||||
}
|
||||
handshakeBegin := time.Now()
|
||||
qConn.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello"))
|
||||
_, buff, err := qConn.ReadMessage()
|
||||
_, buff, err := qConn.ReadBuffer()
|
||||
if e != nil {
|
||||
qConn.listener.Close()
|
||||
return fmt.Errorf("read MsgTunnelHandshake error:%s", err)
|
||||
return nil, fmt.Errorf("read MsgTunnelHandshake error:%s", err)
|
||||
}
|
||||
if buff != nil {
|
||||
gLog.Println(LevelDEBUG, string(buff))
|
||||
gLog.Println(LvDEBUG, string(buff))
|
||||
}
|
||||
|
||||
gLog.Println(LevelINFO, "rtt=", time.Since(handshakeBegin))
|
||||
gLog.Println(LevelDEBUG, "quic connection ok")
|
||||
t.conn = qConn
|
||||
t.setRun(true)
|
||||
go t.readLoop()
|
||||
go t.writeLoop()
|
||||
return nil
|
||||
gLog.Println(LvINFO, "rtt=", time.Since(handshakeBegin))
|
||||
gLog.Println(LvDEBUG, "quic connection ok")
|
||||
return qConn, nil
|
||||
}
|
||||
|
||||
// websocket
|
||||
func (t *P2PTunnel) connectUnderlayTCP() (c underlay, err error) {
|
||||
gLog.Println(LvINFO, "connectUnderlayTCP start")
|
||||
defer gLog.Println(LvINFO, "connectUnderlayTCP end")
|
||||
var qConn *underlayTCP
|
||||
if t.isUnderlayServer() {
|
||||
t.pn.push(t.config.PeerNode, MsgPushUnderlayConnect, nil)
|
||||
qConn, err = listenTCP(t.coneNatPort, TunnelIdleTimeout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listen TCP error:%s", err)
|
||||
}
|
||||
_, buff, err := qConn.ReadBuffer()
|
||||
if err != nil {
|
||||
qConn.listener.Close()
|
||||
return nil, fmt.Errorf("read start msg error:%s", err)
|
||||
}
|
||||
if buff != nil {
|
||||
gLog.Println(LvDEBUG, string(buff))
|
||||
}
|
||||
qConn.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, []byte("OpenP2P,hello2"))
|
||||
gLog.Println(LvDEBUG, "TCP connection ok")
|
||||
return qConn, nil
|
||||
}
|
||||
|
||||
//else
|
||||
t.pn.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, time.Second*5)
|
||||
gLog.Println(LvDEBUG, "TCP dial to ", t.ra.String())
|
||||
qConn, err = dialTCP(t.config.peerIP, t.config.peerConeNatPort)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("TCP dial to %s error:%s", t.ra.String(), err)
|
||||
}
|
||||
handshakeBegin := time.Now()
|
||||
qConn.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello"))
|
||||
_, buff, err := qConn.ReadBuffer()
|
||||
if err != nil {
|
||||
qConn.listener.Close()
|
||||
return nil, fmt.Errorf("read MsgTunnelHandshake error:%s", err)
|
||||
}
|
||||
if buff != nil {
|
||||
gLog.Println(LvDEBUG, string(buff))
|
||||
}
|
||||
|
||||
gLog.Println(LvINFO, "rtt=", time.Since(handshakeBegin))
|
||||
gLog.Println(LvDEBUG, "TCP connection ok")
|
||||
return qConn, nil
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) connectUnderlayTCP6() (c underlay, err error) {
|
||||
gLog.Println(LvINFO, "connectUnderlayTCP start")
|
||||
defer gLog.Println(LvINFO, "connectUnderlayTCP end")
|
||||
var qConn *underlayTCP6
|
||||
if t.isUnderlayServer() {
|
||||
t.pn.push(t.config.PeerNode, MsgPushUnderlayConnect, nil)
|
||||
qConn, err = listenTCP6(t.coneNatPort, TunnelIdleTimeout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("listen TCP error:%s", err)
|
||||
}
|
||||
_, buff, err := qConn.ReadBuffer()
|
||||
if err != nil {
|
||||
qConn.listener.Close()
|
||||
return nil, fmt.Errorf("read start msg error:%s", err)
|
||||
}
|
||||
if buff != nil {
|
||||
gLog.Println(LvDEBUG, string(buff))
|
||||
}
|
||||
qConn.WriteBytes(MsgP2P, MsgTunnelHandshakeAck, []byte("OpenP2P,hello2"))
|
||||
gLog.Println(LvDEBUG, "TCP connection ok")
|
||||
return qConn, nil
|
||||
}
|
||||
|
||||
//else
|
||||
t.pn.read(t.config.PeerNode, MsgPush, MsgPushUnderlayConnect, time.Second*5)
|
||||
gLog.Println(LvDEBUG, "TCP dial to ", t.ra.String())
|
||||
qConn, err = dialTCP6(t.config.IPv6, t.config.peerConeNatPort)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("TCP dial to %s error:%s", t.ra.String(), err)
|
||||
}
|
||||
handshakeBegin := time.Now()
|
||||
qConn.WriteBytes(MsgP2P, MsgTunnelHandshake, []byte("OpenP2P,hello"))
|
||||
_, buff, err := qConn.ReadBuffer()
|
||||
if err != nil {
|
||||
qConn.listener.Close()
|
||||
return nil, fmt.Errorf("read MsgTunnelHandshake error:%s", err)
|
||||
}
|
||||
if buff != nil {
|
||||
gLog.Println(LvDEBUG, string(buff))
|
||||
}
|
||||
|
||||
gLog.Println(LvINFO, "rtt=", time.Since(handshakeBegin))
|
||||
gLog.Println(LvDEBUG, "TCP connection ok")
|
||||
return qConn, nil
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) readLoop() {
|
||||
decryptData := make([]byte, ReadBuffLen+PaddingSize) // 16 bytes for padding
|
||||
gLog.Printf(LevelDEBUG, "%d tunnel readloop start", t.id)
|
||||
gLog.Printf(LvDEBUG, "%d tunnel readloop start", t.id)
|
||||
for t.isRuning() {
|
||||
t.conn.SetReadDeadline(time.Now().Add(TunnelIdleTimeout))
|
||||
head, body, err := t.conn.ReadMessage()
|
||||
head, body, err := t.conn.ReadBuffer()
|
||||
if err != nil {
|
||||
if t.isRuning() {
|
||||
gLog.Printf(LevelERROR, "%d tunnel read error:%s", t.id, err)
|
||||
gLog.Printf(LvERROR, "%d tunnel read error:%s", t.id, err)
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -258,22 +403,22 @@ func (t *P2PTunnel) readLoop() {
|
||||
switch head.SubType {
|
||||
case MsgTunnelHeartbeat:
|
||||
t.conn.WriteBytes(MsgP2P, MsgTunnelHeartbeatAck, nil)
|
||||
gLog.Printf(LevelDEBUG, "%d read tunnel heartbeat", t.id)
|
||||
gLog.Printf(LvDEBUG, "%d read tunnel heartbeat", t.id)
|
||||
case MsgTunnelHeartbeatAck:
|
||||
t.hbMtx.Lock()
|
||||
t.hbTime = time.Now()
|
||||
t.hbMtx.Unlock()
|
||||
gLog.Printf(LevelDEBUG, "%d read tunnel heartbeat ack", t.id)
|
||||
gLog.Printf(LvDEBUG, "%d read tunnel heartbeat ack", t.id)
|
||||
case MsgOverlayData:
|
||||
if len(body) < overlayHeaderSize {
|
||||
continue
|
||||
}
|
||||
overlayID := binary.LittleEndian.Uint64(body[:8])
|
||||
gLog.Printf(LevelDEBUG, "%d tunnel read overlay data %d", t.id, overlayID)
|
||||
gLog.Printf(LvDEBUG, "%d tunnel read overlay data %d", t.id, overlayID)
|
||||
s, ok := t.overlayConns.Load(overlayID)
|
||||
if !ok {
|
||||
// debug level, when overlay connection closed, always has some packet not found tunnel
|
||||
gLog.Printf(LevelDEBUG, "%d tunnel not found overlay connection %d", t.id, overlayID)
|
||||
gLog.Printf(LvDEBUG, "%d tunnel not found overlay connection %d", t.id, overlayID)
|
||||
continue
|
||||
}
|
||||
overlayConn, ok := s.(*overlayConn)
|
||||
@@ -287,10 +432,10 @@ func (t *P2PTunnel) readLoop() {
|
||||
}
|
||||
_, err = overlayConn.Write(payload)
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, "overlay write error:", err)
|
||||
gLog.Println(LvERROR, "overlay write error:", err)
|
||||
}
|
||||
case MsgRelayData:
|
||||
gLog.Printf(LevelDEBUG, "got relay data datalen=%d", head.DataLen)
|
||||
gLog.Printf(LvDEBUG, "got relay data datalen=%d", head.DataLen)
|
||||
if len(body) < 8 {
|
||||
continue
|
||||
}
|
||||
@@ -300,10 +445,10 @@ func (t *P2PTunnel) readLoop() {
|
||||
req := RelayHeartbeat{}
|
||||
err := json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "wrong RelayHeartbeat:%s", err)
|
||||
gLog.Printf(LvERROR, "wrong RelayHeartbeat:%s", err)
|
||||
continue
|
||||
}
|
||||
gLog.Printf(LevelDEBUG, "got MsgRelayHeartbeat from %d:%d", req.RelayTunnelID, req.AppID)
|
||||
gLog.Printf(LvDEBUG, "got MsgRelayHeartbeat from %d:%d", req.RelayTunnelID, req.AppID)
|
||||
relayHead := new(bytes.Buffer)
|
||||
binary.Write(relayHead, binary.LittleEndian, req.RelayTunnelID)
|
||||
msg, _ := newMessage(MsgP2P, MsgRelayHeartbeatAck, &req)
|
||||
@@ -313,26 +458,26 @@ func (t *P2PTunnel) readLoop() {
|
||||
req := RelayHeartbeat{}
|
||||
err := json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "wrong RelayHeartbeat:%s", err)
|
||||
gLog.Printf(LvERROR, "wrong RelayHeartbeat:%s", err)
|
||||
continue
|
||||
}
|
||||
gLog.Printf(LevelDEBUG, "got MsgRelayHeartbeatAck to %d", req.AppID)
|
||||
gLog.Printf(LvDEBUG, "got MsgRelayHeartbeatAck to %d", req.AppID)
|
||||
t.pn.updateAppHeartbeat(req.AppID)
|
||||
case MsgOverlayConnectReq:
|
||||
req := OverlayConnectReq{}
|
||||
err := json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "wrong MsgOverlayConnectReq:%s", err)
|
||||
gLog.Printf(LvERROR, "wrong MsgOverlayConnectReq:%s", err)
|
||||
continue
|
||||
}
|
||||
// app connect only accept token(not relay totp token), avoid someone using the share relay node's token
|
||||
if req.Token != t.pn.config.Token {
|
||||
gLog.Println(LevelERROR, "Access Denied:", req.Token)
|
||||
gLog.Println(LvERROR, "Access Denied:", req.Token)
|
||||
continue
|
||||
}
|
||||
|
||||
overlayID := req.ID
|
||||
gLog.Printf(LevelDEBUG, "App:%d overlayID:%d connect %+v", req.AppID, overlayID, req)
|
||||
gLog.Printf(LvDEBUG, "App:%d overlayID:%d connect %+v", req.AppID, overlayID, req)
|
||||
oConn := overlayConn{
|
||||
tunnel: t,
|
||||
id: overlayID,
|
||||
@@ -347,7 +492,7 @@ func (t *P2PTunnel) readLoop() {
|
||||
oConn.connTCP, err = net.DialTimeout("tcp", fmt.Sprintf("%s:%d", req.DstIP, req.DstPort), time.Second*5)
|
||||
}
|
||||
if err != nil {
|
||||
gLog.Println(LevelERROR, err)
|
||||
gLog.Println(LvERROR, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -365,11 +510,11 @@ func (t *P2PTunnel) readLoop() {
|
||||
req := OverlayDisconnectReq{}
|
||||
err := json.Unmarshal(body, &req)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "wrong OverlayDisconnectRequest:%s", err)
|
||||
gLog.Printf(LvERROR, "wrong OverlayDisconnectRequest:%s", err)
|
||||
continue
|
||||
}
|
||||
overlayID := req.ID
|
||||
gLog.Printf(LevelDEBUG, "%d disconnect overlay connection %d", t.id, overlayID)
|
||||
gLog.Printf(LvDEBUG, "%d disconnect overlay connection %d", t.id, overlayID)
|
||||
i, ok := t.overlayConns.Load(overlayID)
|
||||
if ok {
|
||||
oConn := i.(*overlayConn)
|
||||
@@ -380,32 +525,49 @@ func (t *P2PTunnel) readLoop() {
|
||||
}
|
||||
t.setRun(false)
|
||||
t.conn.Close()
|
||||
gLog.Printf(LevelDEBUG, "%d tunnel readloop end", t.id)
|
||||
gLog.Printf(LvDEBUG, "%d tunnel readloop end", t.id)
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) writeLoop() {
|
||||
func (t *P2PTunnel) heartbeatLoop() {
|
||||
tc := time.NewTicker(TunnelHeartbeatTime)
|
||||
defer tc.Stop()
|
||||
defer gLog.Printf(LevelDEBUG, "%d tunnel writeloop end", t.id)
|
||||
gLog.Printf(LvDEBUG, "%d tunnel heartbeatLoop start", t.id)
|
||||
defer gLog.Printf(LvDEBUG, "%d tunnel heartbeatLoop end", t.id)
|
||||
for t.isRuning() {
|
||||
select {
|
||||
case <-tc.C:
|
||||
// tunnel send
|
||||
err := t.conn.WriteBytes(MsgP2P, MsgTunnelHeartbeat, nil)
|
||||
if err != nil {
|
||||
gLog.Printf(LevelERROR, "%d write tunnel heartbeat error %s", t.id, err)
|
||||
gLog.Printf(LvERROR, "%d write tunnel heartbeat error %s", t.id, err)
|
||||
t.setRun(false)
|
||||
return
|
||||
}
|
||||
gLog.Printf(LevelDEBUG, "%d write tunnel heartbeat ok", t.id)
|
||||
gLog.Printf(LvDEBUG, "%d write tunnel heartbeat ok", t.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) listen() error {
|
||||
gLog.Printf(LevelDEBUG, "p2ptunnel wait for connecting")
|
||||
t.isServer = true
|
||||
return t.handshake()
|
||||
// notify client to connect
|
||||
rsp := PushConnectRsp{
|
||||
Error: 0,
|
||||
Detail: "connect ok",
|
||||
To: t.config.PeerNode,
|
||||
From: t.pn.config.Node,
|
||||
NatType: t.pn.config.natType,
|
||||
HasIPv4: t.pn.config.hasIPv4,
|
||||
IPv6: t.pn.config.IPv6,
|
||||
HasUPNPorNATPMP: t.pn.config.hasUPNPorNATPMP,
|
||||
FromIP: t.pn.config.publicIP,
|
||||
ConeNatPort: t.coneNatPort,
|
||||
ID: t.id,
|
||||
Version: OpenP2PVersion,
|
||||
}
|
||||
t.pn.push(t.config.PeerNode, MsgPushConnectRsp, rsp)
|
||||
gLog.Printf(LvDEBUG, "p2ptunnel wait for connecting")
|
||||
t.tunnelServer = true
|
||||
return t.start()
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) closeOverlayConns(appID uint64) {
|
||||
@@ -424,3 +586,24 @@ func (t *P2PTunnel) closeOverlayConns(appID uint64) {
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) isUnderlayServer() bool {
|
||||
if t.pn.config.natType == NATNone && t.config.peerNatType != NATNone {
|
||||
return true
|
||||
}
|
||||
if t.pn.config.natType != NATNone && t.config.peerNatType == NATNone {
|
||||
return false
|
||||
}
|
||||
// NAT or both has public IP
|
||||
return t.tunnelServer
|
||||
}
|
||||
|
||||
func (t *P2PTunnel) isSupportTCP() bool {
|
||||
if t.config.peerVersion == "" || compareVersion(t.config.peerVersion, LeastSupportTCPVersion) == LESS {
|
||||
return false
|
||||
}
|
||||
if t.pn.config.natType == NATNone || t.config.peerNatType == NATNone {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user