remove duplicate tcp connections

This commit is contained in:
Arceliar 2018-02-17 20:44:23 -06:00
parent 25f00c1c7a
commit 8ba11b86bb

View File

@ -23,11 +23,14 @@ type tcpInterface struct {
serv *net.TCPListener serv *net.TCPListener
mutex sync.Mutex // Protecting the below mutex sync.Mutex // Protecting the below
calls map[string]struct{} calls map[string]struct{}
conns map[tcpInfo](chan struct{})
} }
type tcpKeys struct { type tcpInfo struct {
box boxPubKey box boxPubKey
sig sigPubKey sig sigPubKey
localAddr string // net.IPAddr.String(), not TCPAddr, don't care about port
remoteAddr string
} }
func (iface *tcpInterface) init(core *Core, addr string) { func (iface *tcpInterface) init(core *Core, addr string) {
@ -41,6 +44,7 @@ func (iface *tcpInterface) init(core *Core, addr string) {
panic(err) panic(err)
} }
iface.calls = make(map[string]struct{}) iface.calls = make(map[string]struct{})
iface.conns = make(map[tcpInfo](chan struct{}))
go iface.listener() go iface.listener()
} }
@ -102,8 +106,8 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
if n < len(keys) { /*panic("Partial key packet?") ;*/ if n < len(keys) { /*panic("Partial key packet?") ;*/
return return
} }
ks := tcpKeys{} info := tcpInfo{}
if !tcp_chop_keys(&ks.box, &ks.sig, &keys) { /*panic("Invalid key packet?") ;*/ if !tcp_chop_keys(&info.box, &info.sig, &keys) { /*panic("Invalid key packet?") ;*/
return return
} }
// Quit the parent call if this is a connection to ourself // Quit the parent call if this is a connection to ourself
@ -115,16 +119,40 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
} }
return true return true
} }
if equiv(ks.box[:], iface.core.boxPub[:]) { if equiv(info.box[:], iface.core.boxPub[:]) {
return return
} // testing } // testing
if equiv(ks.sig[:], iface.core.sigPub[:]) { if equiv(info.sig[:], iface.core.sigPub[:]) {
return return
} }
// Check if we already have a connection to this node, close and block if yes
local := sock.LocalAddr().(*net.TCPAddr)
laddr := net.IPAddr{
IP: local.IP,
Zone: local.Zone,
}
info.localAddr = laddr.String()
remote := sock.RemoteAddr().(*net.TCPAddr)
raddr := net.IPAddr{
IP: remote.IP,
Zone: remote.Zone,
}
info.remoteAddr = raddr.String()
iface.mutex.Lock()
if blockChan, isIn := iface.conns[info]; isIn {
iface.mutex.Unlock()
sock.Close()
<-blockChan
return
}
blockChan := make(chan struct{})
iface.conns[info] = blockChan
iface.mutex.Unlock()
defer close(blockChan)
// Note that multiple connections to the same node are allowed // Note that multiple connections to the same node are allowed
// E.g. over different interfaces // E.g. over different interfaces
linkIn := make(chan []byte, 1) linkIn := make(chan []byte, 1)
p := iface.core.peers.newPeer(&ks.box, &ks.sig) //, in, out) p := iface.core.peers.newPeer(&info.box, &info.sig) //, in, out)
in := func(bs []byte) { in := func(bs []byte) {
p.handlePacket(bs, linkIn) p.handlePacket(bs, linkIn)
} }
@ -197,8 +225,8 @@ func (iface *tcpInterface) handler(sock *net.TCPConn) {
p.core.peers.mutex.Unlock() p.core.peers.mutex.Unlock()
close(linkIn) close(linkIn)
}() }()
them := sock.RemoteAddr() them := sock.RemoteAddr().(*net.TCPAddr)
themNodeID := getNodeID(&ks.box) themNodeID := getNodeID(&info.box)
themAddr := address_addrForNodeID(themNodeID) themAddr := address_addrForNodeID(themNodeID)
themAddrString := net.IP(themAddr[:]).String() themAddrString := net.IP(themAddr[:]).String()
themString := fmt.Sprintf("%s@%s", themAddrString, them) themString := fmt.Sprintf("%s@%s", themAddrString, them)