Allow updating Listen during runtime

This commit is contained in:
Neil Alexander 2018-12-30 15:21:09 +00:00
parent f96747181d
commit cb4495902b
No known key found for this signature in database
GPG Key ID: A02A2019A2BB0944
3 changed files with 62 additions and 15 deletions

View File

@ -109,13 +109,14 @@ func (c *Core) UpdateConfig(config *config.NodeConfig) {
components := []chan chan error{
c.admin.reconfigure,
c.searches.reconfigure,
c.dht.reconfigure,
c.sessions.reconfigure,
//c.searches.reconfigure,
//c.dht.reconfigure,
//c.sessions.reconfigure,
//c.peers.reconfigure,
//c.router.reconfigure,
//c.switchTable.reconfigure,
c.tcp.reconfigure,
c.multicast.reconfigure,
c.peers.reconfigure,
c.router.reconfigure,
c.switchTable.reconfigure,
}
for _, component := range components {

View File

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net"
"sync"
"time"
"golang.org/x/net/ipv6"
@ -14,6 +15,8 @@ type multicast struct {
reconfigure chan chan error
sock *ipv6.PacketConn
groupAddr string
myAddr *net.TCPAddr
myAddrMutex sync.RWMutex
}
func (m *multicast) init(core *Core) {
@ -23,6 +26,9 @@ func (m *multicast) init(core *Core) {
for {
select {
case e := <-m.reconfigure:
m.myAddrMutex.Lock()
m.myAddr = m.core.tcp.getAddr()
m.myAddrMutex.Unlock()
e <- nil
}
}
@ -95,13 +101,14 @@ func (m *multicast) interfaces() []net.Interface {
}
func (m *multicast) announce() {
var anAddr net.TCPAddr
m.myAddrMutex.Lock()
m.myAddr = m.core.tcp.getAddr()
m.myAddrMutex.Unlock()
groupAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr)
if err != nil {
panic(err)
}
var anAddr net.TCPAddr
myAddr := m.core.tcp.getAddr()
anAddr.Port = myAddr.Port
destAddr, err := net.ResolveUDPAddr("udp6", m.groupAddr)
if err != nil {
panic(err)
@ -113,6 +120,9 @@ func (m *multicast) announce() {
if err != nil {
panic(err)
}
m.myAddrMutex.RLock()
anAddr.Port = m.myAddr.Port
m.myAddrMutex.RUnlock()
for _, addr := range addrs {
addrIP, _, _ := net.ParseCIDR(addr.String())
if addrIP.To4() != nil {

View File

@ -38,7 +38,9 @@ const tcp_ping_interval = (default_tcp_timeout * 2 / 3)
// The TCP listener and information about active TCP connections, to avoid duplication.
type tcpInterface struct {
core *Core
reconfigure chan chan error
serv net.Listener
serv_stop chan bool
tcp_timeout time.Duration
tcp_addr string
mutex sync.Mutex // Protecting the below
@ -83,10 +85,37 @@ func (iface *tcpInterface) connectSOCKS(socksaddr, peeraddr string) {
// Initializes the struct.
func (iface *tcpInterface) init(core *Core) (err error) {
iface.core = core
iface.serv_stop = make(chan bool, 1)
iface.reconfigure = make(chan chan error, 1)
go func() {
for {
select {
case e := <-iface.reconfigure:
iface.core.configMutex.RLock()
updated := iface.core.config.Listen != iface.core.configOld.Listen
iface.core.configMutex.RUnlock()
if updated {
iface.serv_stop <- true
iface.serv.Close()
e <- iface.listen()
} else {
e <- nil
}
}
}
}()
return iface.listen()
}
func (iface *tcpInterface) listen() error {
var err error
iface.core.configMutex.RLock()
iface.tcp_addr = iface.core.config.Listen
iface.tcp_timeout = time.Duration(iface.core.config.ReadTimeout) * time.Millisecond
iface.core.configMutex.RUnlock()
if iface.tcp_timeout >= 0 && iface.tcp_timeout < default_tcp_timeout {
iface.tcp_timeout = default_tcp_timeout
}
@ -96,6 +125,7 @@ func (iface *tcpInterface) init(core *Core) (err error) {
iface.calls = make(map[string]struct{})
iface.conns = make(map[tcpInfo](chan struct{}))
go iface.listener()
return nil
}
return err
@ -107,10 +137,16 @@ func (iface *tcpInterface) listener() {
iface.core.log.Println("Listening for TCP on:", iface.serv.Addr().String())
for {
sock, err := iface.serv.Accept()
if err != nil {
panic(err)
select {
case <-iface.serv_stop:
iface.core.log.Println("Stopping listener")
return
default:
if err != nil {
panic(err)
}
go iface.handler(sock, true)
}
go iface.handler(sock, true)
}
}
@ -363,12 +399,12 @@ func (iface *tcpInterface) handler(sock net.Conn, incoming bool) {
themAddr := address.AddrForNodeID(themNodeID)
themAddrString := net.IP(themAddr[:]).String()
themString := fmt.Sprintf("%s@%s", themAddrString, them)
iface.core.log.Println("Connected:", themString, "source", us)
iface.core.log.Printf("Connected: %s, source: %s", themString, us)
err = iface.reader(sock, in) // In this goroutine, because of defers
if err == nil {
iface.core.log.Println("Disconnected:", themString, "source", us)
iface.core.log.Printf("Disconnected: %s, source: %s", themString, us)
} else {
iface.core.log.Println("Disconnected:", themString, "source", us, "with error:", err)
iface.core.log.Printf("Disconnected: %s, source: %s, error: %s", themString, us, err)
}
return
}