From 4ef7200df5b45d97a1ee1c9a3dcdc872751f48b6 Mon Sep 17 00:00:00 2001 From: Trial97 Date: Wed, 11 Sep 2019 17:49:25 +0300 Subject: [PATCH] Updated config reload --- agents/dnsagent.go | 77 ++++++++++++++++++++++++++++++++++------------ config/config.go | 39 +++++++++++++---------- 2 files changed, 80 insertions(+), 36 deletions(-) diff --git a/agents/dnsagent.go b/agents/dnsagent.go index fe3bbe4f0..199eb09fd 100644 --- a/agents/dnsagent.go +++ b/agents/dnsagent.go @@ -19,6 +19,7 @@ along with this program. If not, see package agents import ( + "crypto/tls" "fmt" "strings" @@ -42,31 +43,64 @@ type DNSAgent struct { cgrCfg *config.CGRConfig // loaded CGRateS configuration fltrS *engine.FilterS // connection towards FilterS sS rpcclient.RpcClientConnection // connection towards CGR-SessionS component + server *dns.Server +} + +func (da *DNSAgent) newDNSServer() (err error) { + handler := dns.HandlerFunc(func(w dns.ResponseWriter, m *dns.Msg) { + go da.handleMessage(w, m) + }) + + if strings.HasSuffix(da.cgrCfg.DNSAgentCfg().ListenNet, utils.TLSNoCaps) { + cert, err := tls.LoadX509KeyPair(da.cgrCfg.TlsCfg().ServerCerificate, da.cgrCfg.TlsCfg().ServerKey) + if err != nil { + return err + } + + config := tls.Config{ + Certificates: []tls.Certificate{cert}, + } + + da.server = &dns.Server{ + Addr: da.cgrCfg.DNSAgentCfg().Listen, + Net: "tcp-tls", + TLSConfig: &config, + Handler: handler, + } + } else { + da.server = &dns.Server{Addr: da.cgrCfg.DNSAgentCfg().Listen, Net: da.cgrCfg.DNSAgentCfg().ListenNet, Handler: handler} + } + return } // ListenAndServe will run the DNS handler doing also the connection to listen address -func (da *DNSAgent) ListenAndServe() error { +func (da *DNSAgent) ListenAndServe() (err error) { utils.Logger.Info(fmt.Sprintf("<%s> start listening on <%s:%s>", utils.DNSAgent, da.cgrCfg.DNSAgentCfg().ListenNet, da.cgrCfg.DNSAgentCfg().Listen)) - if strings.HasSuffix(da.cgrCfg.DNSAgentCfg().ListenNet, utils.TLSNoCaps) { - return dns.ListenAndServeTLS( - da.cgrCfg.DNSAgentCfg().Listen, - da.cgrCfg.TlsCfg().ServerCerificate, - da.cgrCfg.TlsCfg().ServerKey, - dns.HandlerFunc( - func(w dns.ResponseWriter, m *dns.Msg) { - go da.handleMessage(w, m) - }), - ) + errChan := make(chan error, 1) + rldChan := da.cgrCfg.GetReloadChan(config.DNSAgentJson) + + if err = da.newDNSServer(); err != nil { + return + } + lisenAndServe := func() { + errChan <- da.server.ListenAndServe() + } + go lisenAndServe() + for { + select { + case err = <-errChan: + return + case <-rldChan: + if err = da.Shutdown(); err != nil { + return + } + if err = da.newDNSServer(); err != nil { + return + } + go lisenAndServe() //restart the gorutine + } } - return dns.ListenAndServe( - da.cgrCfg.DNSAgentCfg().Listen, - da.cgrCfg.DNSAgentCfg().ListenNet, - dns.HandlerFunc( - func(w dns.ResponseWriter, m *dns.Msg) { - go da.handleMessage(w, m) - }), - ) } // handleMessage is the entry point of all DNS requests @@ -321,3 +355,8 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor, } return true, nil } + +// Shutdown stops the DNS server +func (da *DNSAgent) Shutdown() error { + return da.server.Shutdown() +} diff --git a/config/config.go b/config/config.go index 69be9b2af..6173d610f 100755 --- a/config/config.go +++ b/config/config.go @@ -179,8 +179,6 @@ func NewDefaultCGRConfig() (cfg *CGRConfig, err error) { cfg.ConfigReloads[utils.CDRC] <- struct{}{} // Unlock the channel cfg.ConfigReloads[utils.CDRE] = make(chan struct{}, 1) cfg.ConfigReloads[utils.CDRE] <- struct{}{} // Unlock the channel - cfg.ConfigReloads[utils.SURETAX] = make(chan struct{}, 1) - cfg.ConfigReloads[utils.SURETAX] <- struct{}{} // Unlock the channel cfg.ConfigReloads[utils.DIAMETER_AGENT] = make(chan struct{}, 1) cfg.ConfigReloads[utils.DIAMETER_AGENT] <- struct{}{} // Unlock the channel cfg.ConfigReloads[utils.SMAsterisk] = make(chan struct{}, 1) @@ -1122,25 +1120,32 @@ func (cfg *CGRConfig) loadErsCfg(jsnCfg *CgrJsonCfg) (err error) { return cfg.ersCfg.loadFromJsonCfg(jsnERsCfg, cfg.GeneralCfg().RSRSep, cfg.dfltEvRdr) } -// Use locking to retrieve the configuration, possibility later for runtime reload -func (self *CGRConfig) SureTaxCfg() *SureTaxCfg { - cfgChan := <-self.ConfigReloads[utils.SURETAX] // Lock config for read or reloads - defer func() { self.ConfigReloads[utils.SURETAX] <- cfgChan }() - return self.sureTaxCfg +// SureTaxCfg use locking to retrieve the configuration, possibility later for runtime reload +func (cfg *CGRConfig) SureTaxCfg() *SureTaxCfg { + cfg.lks[SURETAX_JSON].Lock() + defer cfg.lks[SURETAX_JSON].Unlock() + return cfg.sureTaxCfg } -func (self *CGRConfig) DiameterAgentCfg() *DiameterAgentCfg { - cfgChan := <-self.ConfigReloads[utils.DIAMETER_AGENT] // Lock config for read or reloads - defer func() { self.ConfigReloads[utils.DIAMETER_AGENT] <- cfgChan }() - return self.diameterAgentCfg +// DiameterAgentCfg returns the config for Diameter Agent +func (cfg *CGRConfig) DiameterAgentCfg() *DiameterAgentCfg { + cfg.lks[DA_JSN].Lock() + defer cfg.lks[DA_JSN].Unlock() + return cfg.diameterAgentCfg } -func (self *CGRConfig) RadiusAgentCfg() *RadiusAgentCfg { - return self.radiusAgentCfg +// RadiusAgentCfg returns the config for Radius Agent +func (cfg *CGRConfig) RadiusAgentCfg() *RadiusAgentCfg { + cfg.lks[RA_JSN].Lock() + defer cfg.lks[RA_JSN].Unlock() + return cfg.radiusAgentCfg } -func (self *CGRConfig) DNSAgentCfg() *DNSAgentCfg { - return self.dnsAgentCfg +// DNSAgentCfg returns the config for DNS Agent +func (cfg *CGRConfig) DNSAgentCfg() *DNSAgentCfg { + cfg.lks[DNSAgentJson].Lock() + defer cfg.lks[DNSAgentJson].Unlock() + return cfg.dnsAgentCfg } func (cfg *CGRConfig) AttributeSCfg() *AttributeSCfg { @@ -1534,6 +1539,7 @@ func (cfg *CGRConfig) reloadSection(section string) (err error) { } fallthrough case DNSAgentJson: + cfg.rldChans[DNSAgentJson] <- struct{}{} if !fall { break } @@ -1578,7 +1584,7 @@ func (cfg *CGRConfig) reloadSection(section string) (err error) { break } fallthrough - case SURETAX_JSON: + case SURETAX_JSON: // doesn't need to be reloaded if !fall { break } @@ -1607,7 +1613,6 @@ func (cfg *CGRConfig) reloadSection(section string) (err error) { if !fall { break } - fallthrough } return }