mirror of
https://github.com/cwinfo/yggdrasil-go.git
synced 2024-11-22 21:10:29 +00:00
make the main library reconfiguration more actor-friendly
This commit is contained in:
parent
aa30c6cc98
commit
a3d4d8125b
@ -117,20 +117,21 @@ func (c *Core) UpdateConfig(config *config.NodeConfig) {
|
|||||||
|
|
||||||
errors := 0
|
errors := 0
|
||||||
|
|
||||||
components := []chan chan error{
|
// Each reconfigure function should pass any errors to the channel, then close it
|
||||||
c.router.searches.reconfigure,
|
components := []func(chan error){
|
||||||
c.router.dht.reconfigure,
|
c.link.reconfigure,
|
||||||
c.router.sessions.reconfigure,
|
|
||||||
c.peers.reconfigure,
|
c.peers.reconfigure,
|
||||||
c.router.reconfigure,
|
c.router.reconfigure,
|
||||||
|
c.router.dht.reconfigure,
|
||||||
|
c.router.searches.reconfigure,
|
||||||
|
c.router.sessions.reconfigure,
|
||||||
c.switchTable.reconfigure,
|
c.switchTable.reconfigure,
|
||||||
c.link.reconfigure,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, component := range components {
|
for _, component := range components {
|
||||||
response := make(chan error)
|
response := make(chan error)
|
||||||
component <- response
|
go component(response)
|
||||||
if err := <-response; err != nil {
|
for err := range response {
|
||||||
c.log.Errorln(err)
|
c.log.Errorln(err)
|
||||||
errors++
|
errors++
|
||||||
}
|
}
|
||||||
|
@ -65,11 +65,10 @@ type dhtReqKey struct {
|
|||||||
|
|
||||||
// The main DHT struct.
|
// The main DHT struct.
|
||||||
type dht struct {
|
type dht struct {
|
||||||
router *router
|
router *router
|
||||||
reconfigure chan chan error
|
nodeID crypto.NodeID
|
||||||
nodeID crypto.NodeID
|
reqs map[dhtReqKey]time.Time // Keeps track of recent outstanding requests
|
||||||
reqs map[dhtReqKey]time.Time // Keeps track of recent outstanding requests
|
callbacks map[dhtReqKey][]dht_callbackInfo // Search and admin lookup callbacks
|
||||||
callbacks map[dhtReqKey][]dht_callbackInfo // Search and admin lookup callbacks
|
|
||||||
// These next two could be replaced by a single linked list or similar...
|
// These next two could be replaced by a single linked list or similar...
|
||||||
table map[crypto.NodeID]*dhtInfo
|
table map[crypto.NodeID]*dhtInfo
|
||||||
imp []*dhtInfo
|
imp []*dhtInfo
|
||||||
@ -78,18 +77,16 @@ type dht struct {
|
|||||||
// Initializes the DHT.
|
// Initializes the DHT.
|
||||||
func (t *dht) init(r *router) {
|
func (t *dht) init(r *router) {
|
||||||
t.router = r
|
t.router = r
|
||||||
t.reconfigure = make(chan chan error, 1)
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
e := <-t.reconfigure
|
|
||||||
e <- nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
t.nodeID = *t.router.core.NodeID()
|
t.nodeID = *t.router.core.NodeID()
|
||||||
t.callbacks = make(map[dhtReqKey][]dht_callbackInfo)
|
t.callbacks = make(map[dhtReqKey][]dht_callbackInfo)
|
||||||
t.reset()
|
t.reset()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *dht) reconfigure(e chan error) {
|
||||||
|
defer close(e)
|
||||||
|
// This is where reconfiguration would go, if we had anything to do
|
||||||
|
}
|
||||||
|
|
||||||
// Resets the DHT in response to coord changes.
|
// Resets the DHT in response to coord changes.
|
||||||
// This empties all info from the DHT and drops outstanding requests.
|
// This empties all info from the DHT and drops outstanding requests.
|
||||||
func (t *dht) reset() {
|
func (t *dht) reset() {
|
||||||
|
@ -21,11 +21,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type link struct {
|
type link struct {
|
||||||
core *Core
|
core *Core
|
||||||
reconfigure chan chan error
|
mutex sync.RWMutex // protects interfaces below
|
||||||
mutex sync.RWMutex // protects interfaces below
|
interfaces map[linkInfo]*linkInterface
|
||||||
interfaces map[linkInfo]*linkInterface
|
tcp tcp // TCP interface support
|
||||||
tcp tcp // TCP interface support
|
|
||||||
// TODO timeout (to remove from switch), read from config.ReadTimeout
|
// TODO timeout (to remove from switch), read from config.ReadTimeout
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +60,6 @@ func (l *link) init(c *Core) error {
|
|||||||
l.core = c
|
l.core = c
|
||||||
l.mutex.Lock()
|
l.mutex.Lock()
|
||||||
l.interfaces = make(map[linkInfo]*linkInterface)
|
l.interfaces = make(map[linkInfo]*linkInterface)
|
||||||
l.reconfigure = make(chan chan error)
|
|
||||||
l.mutex.Unlock()
|
l.mutex.Unlock()
|
||||||
|
|
||||||
if err := l.tcp.init(l); err != nil {
|
if err := l.tcp.init(l); err != nil {
|
||||||
@ -69,22 +67,18 @@ func (l *link) init(c *Core) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
e := <-l.reconfigure
|
|
||||||
tcpresponse := make(chan error)
|
|
||||||
l.tcp.reconfigure <- tcpresponse
|
|
||||||
if err := <-tcpresponse; err != nil {
|
|
||||||
e <- err
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
e <- nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (l *link) reconfigure(e chan error) {
|
||||||
|
defer close(e)
|
||||||
|
tcpResponse := make(chan error)
|
||||||
|
go l.tcp.reconfigure(tcpResponse)
|
||||||
|
for err := range tcpResponse {
|
||||||
|
e <- err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (l *link) call(uri string, sintf string) error {
|
func (l *link) call(uri string, sintf string) error {
|
||||||
u, err := url.Parse(uri)
|
u, err := url.Parse(uri)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -21,10 +21,9 @@ import (
|
|||||||
// In most cases, this involves passing the packet to the handler for outgoing traffic to another peer.
|
// In most cases, this involves passing the packet to the handler for outgoing traffic to another peer.
|
||||||
// In other cases, it's link protocol traffic used to build the spanning tree, in which case this checks signatures and passes the message along to the switch.
|
// In other cases, it's link protocol traffic used to build the spanning tree, in which case this checks signatures and passes the message along to the switch.
|
||||||
type peers struct {
|
type peers struct {
|
||||||
core *Core
|
core *Core
|
||||||
reconfigure chan chan error
|
mutex sync.Mutex // Synchronize writes to atomic
|
||||||
mutex sync.Mutex // Synchronize writes to atomic
|
ports atomic.Value //map[switchPort]*peer, use CoW semantics
|
||||||
ports atomic.Value //map[switchPort]*peer, use CoW semantics
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the peers struct.
|
// Initializes the peers struct.
|
||||||
@ -33,13 +32,11 @@ func (ps *peers) init(c *Core) {
|
|||||||
defer ps.mutex.Unlock()
|
defer ps.mutex.Unlock()
|
||||||
ps.putPorts(make(map[switchPort]*peer))
|
ps.putPorts(make(map[switchPort]*peer))
|
||||||
ps.core = c
|
ps.core = c
|
||||||
ps.reconfigure = make(chan chan error, 1)
|
}
|
||||||
go func() {
|
|
||||||
for {
|
func (ps *peers) reconfigure(e chan error) {
|
||||||
e := <-ps.reconfigure
|
defer close(e)
|
||||||
e <- nil
|
// This is where reconfiguration would go, if we had anything to do
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if an incoming peer connection to a key is allowed, either
|
// Returns true if an incoming peer connection to a key is allowed, either
|
||||||
|
@ -35,24 +35,22 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// The router struct has channels to/from the adapter device and a self peer (0), which is how messages are passed between this node and the peers/switch layer.
|
// The router struct has channels to/from the adapter device and a self peer (0), which is how messages are passed between this node and the peers/switch layer.
|
||||||
// The router's mainLoop goroutine is responsible for managing all information related to the dht, searches, and crypto sessions.
|
// The router's phony.Inbox goroutine is responsible for managing all information related to the dht, searches, and crypto sessions.
|
||||||
type router struct {
|
type router struct {
|
||||||
phony.Inbox
|
phony.Inbox
|
||||||
core *Core
|
core *Core
|
||||||
reconfigure chan chan error
|
addr address.Address
|
||||||
addr address.Address
|
subnet address.Subnet
|
||||||
subnet address.Subnet
|
out func([]byte) // packets we're sending to the network, link to peer's "in"
|
||||||
out func([]byte) // packets we're sending to the network, link to peer's "in"
|
dht dht
|
||||||
dht dht
|
nodeinfo nodeinfo
|
||||||
nodeinfo nodeinfo
|
searches searches
|
||||||
searches searches
|
sessions sessions
|
||||||
sessions sessions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the router struct, which includes setting up channels to/from the adapter.
|
// Initializes the router struct, which includes setting up channels to/from the adapter.
|
||||||
func (r *router) init(core *Core) {
|
func (r *router) init(core *Core) {
|
||||||
r.core = core
|
r.core = core
|
||||||
r.reconfigure = make(chan chan error, 1)
|
|
||||||
r.addr = *address.AddrForNodeID(&r.dht.nodeID)
|
r.addr = *address.AddrForNodeID(&r.dht.nodeID)
|
||||||
r.subnet = *address.SubnetForNodeID(&r.dht.nodeID)
|
r.subnet = *address.SubnetForNodeID(&r.dht.nodeID)
|
||||||
self := linkInterface{
|
self := linkInterface{
|
||||||
@ -75,10 +73,26 @@ func (r *router) init(core *Core) {
|
|||||||
r.sessions.init(r)
|
r.sessions.init(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Starts the mainLoop goroutine.
|
func (r *router) reconfigure(e chan error) {
|
||||||
|
defer close(e)
|
||||||
|
var errs []error
|
||||||
|
// Reconfigure the router
|
||||||
|
<-r.SyncExec(func() {
|
||||||
|
current := r.core.config.GetCurrent()
|
||||||
|
err := r.nodeinfo.setNodeInfo(current.NodeInfo, current.NodeInfoPrivacy)
|
||||||
|
if err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
for _, err := range errs {
|
||||||
|
e <- err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Starts the tickerLoop goroutine.
|
||||||
func (r *router) start() error {
|
func (r *router) start() error {
|
||||||
r.core.log.Infoln("Starting router")
|
r.core.log.Infoln("Starting router")
|
||||||
go r._mainLoop()
|
go r.tickerLoop()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,24 +122,17 @@ func (r *router) reset(from phony.Actor) {
|
|||||||
|
|
||||||
// TODO remove reconfigure so this is just a ticker loop
|
// TODO remove reconfigure so this is just a ticker loop
|
||||||
// and then find something better than a ticker loop to schedule things...
|
// and then find something better than a ticker loop to schedule things...
|
||||||
func (r *router) _mainLoop() {
|
func (r *router) tickerLoop() {
|
||||||
ticker := time.NewTicker(time.Second)
|
ticker := time.NewTicker(time.Second)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for {
|
for {
|
||||||
select {
|
<-ticker.C
|
||||||
case <-ticker.C:
|
<-r.SyncExec(func() {
|
||||||
<-r.SyncExec(func() {
|
// Any periodic maintenance stuff goes here
|
||||||
// Any periodic maintenance stuff goes here
|
r.core.switchTable.doMaintenance()
|
||||||
r.core.switchTable.doMaintenance()
|
r.dht.doMaintenance()
|
||||||
r.dht.doMaintenance()
|
r.sessions.cleanup()
|
||||||
r.sessions.cleanup()
|
})
|
||||||
})
|
|
||||||
case e := <-r.reconfigure:
|
|
||||||
<-r.SyncExec(func() {
|
|
||||||
current := r.core.config.GetCurrent()
|
|
||||||
e <- r.nodeinfo.setNodeInfo(current.NodeInfo, current.NodeInfoPrivacy)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,24 +45,21 @@ type searchInfo struct {
|
|||||||
|
|
||||||
// This stores a map of active searches.
|
// This stores a map of active searches.
|
||||||
type searches struct {
|
type searches struct {
|
||||||
router *router
|
router *router
|
||||||
reconfigure chan chan error
|
searches map[crypto.NodeID]*searchInfo
|
||||||
searches map[crypto.NodeID]*searchInfo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initializes the searches struct.
|
// Initializes the searches struct.
|
||||||
func (s *searches) init(r *router) {
|
func (s *searches) init(r *router) {
|
||||||
s.router = r
|
s.router = r
|
||||||
s.reconfigure = make(chan chan error, 1)
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
e := <-s.reconfigure
|
|
||||||
e <- nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
s.searches = make(map[crypto.NodeID]*searchInfo)
|
s.searches = make(map[crypto.NodeID]*searchInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *searches) reconfigure(e chan error) {
|
||||||
|
defer close(e)
|
||||||
|
// This is where reconfiguration would go, if we had anything to do
|
||||||
|
}
|
||||||
|
|
||||||
// Creates a new search info, adds it to the searches struct, and returns a pointer to the info.
|
// Creates a new search info, adds it to the searches struct, and returns a pointer to the info.
|
||||||
func (s *searches) createSearch(dest *crypto.NodeID, mask *crypto.NodeID, callback func(*sessionInfo, error)) *searchInfo {
|
func (s *searches) createSearch(dest *crypto.NodeID, mask *crypto.NodeID, callback func(*sessionInfo, error)) *searchInfo {
|
||||||
info := searchInfo{
|
info := searchInfo{
|
||||||
|
@ -40,7 +40,6 @@ func (h nonceHeap) peek() *crypto.BoxNonce { return &h[0] }
|
|||||||
type sessionInfo struct {
|
type sessionInfo struct {
|
||||||
phony.Inbox // Protects all of the below, use it any time you read/change the contents of a session
|
phony.Inbox // Protects all of the below, use it any time you read/change the contents of a session
|
||||||
sessions *sessions //
|
sessions *sessions //
|
||||||
reconfigure chan chan error //
|
|
||||||
theirAddr address.Address //
|
theirAddr address.Address //
|
||||||
theirSubnet address.Subnet //
|
theirSubnet address.Subnet //
|
||||||
theirPermPub crypto.BoxPubKey //
|
theirPermPub crypto.BoxPubKey //
|
||||||
@ -74,6 +73,11 @@ type sessionInfo struct {
|
|||||||
callbacks []chan func() // Finished work from crypto workers
|
callbacks []chan func() // Finished work from crypto workers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sinfo *sessionInfo) reconfigure(e chan error) {
|
||||||
|
defer close(e)
|
||||||
|
// This is where reconfiguration would go, if we had anything to do
|
||||||
|
}
|
||||||
|
|
||||||
// TODO remove this, call SyncExec directly
|
// TODO remove this, call SyncExec directly
|
||||||
func (sinfo *sessionInfo) doFunc(f func()) {
|
func (sinfo *sessionInfo) doFunc(f func()) {
|
||||||
<-sinfo.SyncExec(f)
|
<-sinfo.SyncExec(f)
|
||||||
@ -140,7 +144,6 @@ type sessions struct {
|
|||||||
router *router
|
router *router
|
||||||
listener *Listener
|
listener *Listener
|
||||||
listenerMutex sync.Mutex
|
listenerMutex sync.Mutex
|
||||||
reconfigure chan chan error
|
|
||||||
lastCleanup time.Time
|
lastCleanup time.Time
|
||||||
isAllowedHandler func(pubkey *crypto.BoxPubKey, initiator bool) bool // Returns true or false if session setup is allowed
|
isAllowedHandler func(pubkey *crypto.BoxPubKey, initiator bool) bool // Returns true or false if session setup is allowed
|
||||||
isAllowedMutex sync.RWMutex // Protects the above
|
isAllowedMutex sync.RWMutex // Protects the above
|
||||||
@ -152,30 +155,28 @@ type sessions struct {
|
|||||||
// Initializes the session struct.
|
// Initializes the session struct.
|
||||||
func (ss *sessions) init(r *router) {
|
func (ss *sessions) init(r *router) {
|
||||||
ss.router = r
|
ss.router = r
|
||||||
ss.reconfigure = make(chan chan error, 1)
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
e := <-ss.reconfigure
|
|
||||||
responses := make(map[crypto.Handle]chan error)
|
|
||||||
for index, session := range ss.sinfos {
|
|
||||||
responses[index] = make(chan error)
|
|
||||||
session.reconfigure <- responses[index]
|
|
||||||
}
|
|
||||||
for _, response := range responses {
|
|
||||||
if err := <-response; err != nil {
|
|
||||||
e <- err
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e <- nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
ss.permShared = make(map[crypto.BoxPubKey]*crypto.BoxSharedKey)
|
ss.permShared = make(map[crypto.BoxPubKey]*crypto.BoxSharedKey)
|
||||||
ss.sinfos = make(map[crypto.Handle]*sessionInfo)
|
ss.sinfos = make(map[crypto.Handle]*sessionInfo)
|
||||||
ss.byTheirPerm = make(map[crypto.BoxPubKey]*crypto.Handle)
|
ss.byTheirPerm = make(map[crypto.BoxPubKey]*crypto.Handle)
|
||||||
ss.lastCleanup = time.Now()
|
ss.lastCleanup = time.Now()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ss *sessions) reconfigure(e chan error) {
|
||||||
|
defer close(e)
|
||||||
|
responses := make(map[crypto.Handle]chan error)
|
||||||
|
<-ss.router.SyncExec(func() {
|
||||||
|
for index, session := range ss.sinfos {
|
||||||
|
responses[index] = make(chan error)
|
||||||
|
go session.reconfigure(responses[index])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
for _, response := range responses {
|
||||||
|
for err := range response {
|
||||||
|
e <- err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Determines whether the session with a given publickey is allowed based on
|
// Determines whether the session with a given publickey is allowed based on
|
||||||
// session firewall rules.
|
// session firewall rules.
|
||||||
func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) bool {
|
func (ss *sessions) isSessionAllowed(pubkey *crypto.BoxPubKey, initiator bool) bool {
|
||||||
@ -215,7 +216,6 @@ func (ss *sessions) createSession(theirPermKey *crypto.BoxPubKey) *sessionInfo {
|
|||||||
}
|
}
|
||||||
sinfo := sessionInfo{}
|
sinfo := sessionInfo{}
|
||||||
sinfo.sessions = ss
|
sinfo.sessions = ss
|
||||||
sinfo.reconfigure = make(chan chan error, 1)
|
|
||||||
sinfo.theirPermPub = *theirPermKey
|
sinfo.theirPermPub = *theirPermKey
|
||||||
sinfo.sharedPermKey = *ss.getSharedKey(&ss.router.core.boxPriv, &sinfo.theirPermPub)
|
sinfo.sharedPermKey = *ss.getSharedKey(&ss.router.core.boxPriv, &sinfo.theirPermPub)
|
||||||
pub, priv := crypto.NewBoxKeys()
|
pub, priv := crypto.NewBoxKeys()
|
||||||
|
@ -165,7 +165,6 @@ type switchData struct {
|
|||||||
// All the information stored by the switch.
|
// All the information stored by the switch.
|
||||||
type switchTable struct {
|
type switchTable struct {
|
||||||
core *Core
|
core *Core
|
||||||
reconfigure chan chan error
|
|
||||||
key crypto.SigPubKey // Our own key
|
key crypto.SigPubKey // Our own key
|
||||||
time time.Time // Time when locator.tstamp was last updated
|
time time.Time // Time when locator.tstamp was last updated
|
||||||
drop map[crypto.SigPubKey]int64 // Tstamp associated with a dropped root
|
drop map[crypto.SigPubKey]int64 // Tstamp associated with a dropped root
|
||||||
@ -186,7 +185,6 @@ const SwitchQueueTotalMinSize = 4 * 1024 * 1024
|
|||||||
func (t *switchTable) init(core *Core) {
|
func (t *switchTable) init(core *Core) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
t.core = core
|
t.core = core
|
||||||
t.reconfigure = make(chan chan error, 1)
|
|
||||||
t.key = t.core.sigPub
|
t.key = t.core.sigPub
|
||||||
locator := switchLocator{root: t.key, tstamp: now.Unix()}
|
locator := switchLocator{root: t.key, tstamp: now.Unix()}
|
||||||
peers := make(map[switchPort]peerInfo)
|
peers := make(map[switchPort]peerInfo)
|
||||||
@ -201,6 +199,13 @@ func (t *switchTable) init(core *Core) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *switchTable) reconfigure(e chan error) {
|
||||||
|
go func() {
|
||||||
|
defer close(e)
|
||||||
|
// This is where reconfiguration would go, if we had anything useful to do.
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
// Safely gets a copy of this node's locator.
|
// Safely gets a copy of this node's locator.
|
||||||
func (t *switchTable) getLocator() switchLocator {
|
func (t *switchTable) getLocator() switchLocator {
|
||||||
t.mutex.RLock()
|
t.mutex.RLock()
|
||||||
@ -566,12 +571,7 @@ func (t *switchTable) getTable() lookupTable {
|
|||||||
// Starts the switch worker
|
// Starts the switch worker
|
||||||
func (t *switchTable) start() error {
|
func (t *switchTable) start() error {
|
||||||
t.core.log.Infoln("Starting switch")
|
t.core.log.Infoln("Starting switch")
|
||||||
go func() {
|
// There's actually nothing to do to start it...
|
||||||
// TODO find a better way to handle reconfiguration... and have the switch do something with the new configuration
|
|
||||||
for ch := range t.reconfigure {
|
|
||||||
ch <- nil
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,12 +33,11 @@ const tcp_ping_interval = (default_timeout * 2 / 3)
|
|||||||
|
|
||||||
// The TCP listener and information about active TCP connections, to avoid duplication.
|
// The TCP listener and information about active TCP connections, to avoid duplication.
|
||||||
type tcp struct {
|
type tcp struct {
|
||||||
link *link
|
link *link
|
||||||
reconfigure chan chan error
|
mutex sync.Mutex // Protecting the below
|
||||||
mutex sync.Mutex // Protecting the below
|
listeners map[string]*TcpListener
|
||||||
listeners map[string]*TcpListener
|
calls map[string]struct{}
|
||||||
calls map[string]struct{}
|
conns map[linkInfo](chan struct{})
|
||||||
conns map[linkInfo](chan struct{})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TcpListener is a stoppable TCP listener interface. These are typically
|
// TcpListener is a stoppable TCP listener interface. These are typically
|
||||||
@ -76,49 +75,12 @@ func (t *tcp) getAddr() *net.TCPAddr {
|
|||||||
// Initializes the struct.
|
// Initializes the struct.
|
||||||
func (t *tcp) init(l *link) error {
|
func (t *tcp) init(l *link) error {
|
||||||
t.link = l
|
t.link = l
|
||||||
t.reconfigure = make(chan chan error, 1)
|
|
||||||
t.mutex.Lock()
|
t.mutex.Lock()
|
||||||
t.calls = make(map[string]struct{})
|
t.calls = make(map[string]struct{})
|
||||||
t.conns = make(map[linkInfo](chan struct{}))
|
t.conns = make(map[linkInfo](chan struct{}))
|
||||||
t.listeners = make(map[string]*TcpListener)
|
t.listeners = make(map[string]*TcpListener)
|
||||||
t.mutex.Unlock()
|
t.mutex.Unlock()
|
||||||
|
|
||||||
go func() {
|
|
||||||
for {
|
|
||||||
e := <-t.reconfigure
|
|
||||||
t.link.core.config.Mutex.RLock()
|
|
||||||
added := util.Difference(t.link.core.config.Current.Listen, t.link.core.config.Previous.Listen)
|
|
||||||
deleted := util.Difference(t.link.core.config.Previous.Listen, t.link.core.config.Current.Listen)
|
|
||||||
t.link.core.config.Mutex.RUnlock()
|
|
||||||
if len(added) > 0 || len(deleted) > 0 {
|
|
||||||
for _, a := range added {
|
|
||||||
if a[:6] != "tcp://" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err := t.listen(a[6:]); err != nil {
|
|
||||||
e <- err
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, d := range deleted {
|
|
||||||
if d[:6] != "tcp://" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
t.mutex.Lock()
|
|
||||||
if listener, ok := t.listeners[d[6:]]; ok {
|
|
||||||
t.mutex.Unlock()
|
|
||||||
listener.Stop <- true
|
|
||||||
} else {
|
|
||||||
t.mutex.Unlock()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e <- nil
|
|
||||||
} else {
|
|
||||||
e <- nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
t.link.core.config.Mutex.RLock()
|
t.link.core.config.Mutex.RLock()
|
||||||
defer t.link.core.config.Mutex.RUnlock()
|
defer t.link.core.config.Mutex.RUnlock()
|
||||||
for _, listenaddr := range t.link.core.config.Current.Listen {
|
for _, listenaddr := range t.link.core.config.Current.Listen {
|
||||||
@ -133,6 +95,36 @@ func (t *tcp) init(l *link) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *tcp) reconfigure(e chan error) {
|
||||||
|
defer close(e)
|
||||||
|
t.link.core.config.Mutex.RLock()
|
||||||
|
added := util.Difference(t.link.core.config.Current.Listen, t.link.core.config.Previous.Listen)
|
||||||
|
deleted := util.Difference(t.link.core.config.Previous.Listen, t.link.core.config.Current.Listen)
|
||||||
|
t.link.core.config.Mutex.RUnlock()
|
||||||
|
if len(added) > 0 || len(deleted) > 0 {
|
||||||
|
for _, a := range added {
|
||||||
|
if a[:6] != "tcp://" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, err := t.listen(a[6:]); err != nil {
|
||||||
|
e <- err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, d := range deleted {
|
||||||
|
if d[:6] != "tcp://" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
t.mutex.Lock()
|
||||||
|
if listener, ok := t.listeners[d[6:]]; ok {
|
||||||
|
t.mutex.Unlock()
|
||||||
|
listener.Stop <- true
|
||||||
|
} else {
|
||||||
|
t.mutex.Unlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *tcp) listen(listenaddr string) (*TcpListener, error) {
|
func (t *tcp) listen(listenaddr string) (*TcpListener, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user