diff --git a/agents/radagent.go b/agents/radagent.go index dcc6a41a9..50ef499ae 100644 --- a/agents/radagent.go +++ b/agents/radagent.go @@ -335,3 +335,9 @@ func (ra *RadiusAgent) ListenAndServe() (err error) { err = <-errListen return } + +// SetSessionSConnection sets the new connection to the session service +// only used on reload +func (ra *RadiusAgent) SetSessionSConnection(sS rpcclient.RpcClientConnection) { + ra.sessionS = sS +} diff --git a/cmd/cgr-engine/cgr-engine.go b/cmd/cgr-engine/cgr-engine.go index 9a7b8a2d3..fae07b297 100644 --- a/cmd/cgr-engine/cgr-engine.go +++ b/cmd/cgr-engine/cgr-engine.go @@ -194,42 +194,6 @@ func startDiameterAgent(internalSsChan, internalDispatcherSChan chan rpcclient.R exitChan <- true } -func startRadiusAgent(internalSMGChan, internalDispatcherSChan chan rpcclient.RpcClientConnection, - filterSChan chan *engine.FilterS, exitChan chan bool) { - filterS := <-filterSChan - filterSChan <- filterS - utils.Logger.Info("Starting CGRateS RadiusAgent service") - var err error - var smgConn rpcclient.RpcClientConnection - intSMGChan := internalSMGChan - if cfg.DispatcherSCfg().Enabled { - intSMGChan = internalDispatcherSChan - } - - smgConn, err = engine.NewRPCPool(rpcclient.POOL_FIRST, - cfg.TlsCfg().ClientKey, - cfg.TlsCfg().ClientCerificate, cfg.TlsCfg().CaCertificate, - cfg.GeneralCfg().ConnectAttempts, cfg.GeneralCfg().Reconnects, - cfg.GeneralCfg().ConnectTimeout, cfg.GeneralCfg().ReplyTimeout, - cfg.RadiusAgentCfg().SessionSConns, intSMGChan, false) - if err != nil { - utils.Logger.Crit(fmt.Sprintf("<%s> Could not connect to SMG: %s", utils.RadiusAgent, err.Error())) - exitChan <- true - return - } - - ra, err := agents.NewRadiusAgent(cfg, filterS, smgConn) - if err != nil { - utils.Logger.Err(fmt.Sprintf("<%s> error: <%s>", utils.RadiusAgent, err.Error())) - exitChan <- true - return - } - if err = ra.ListenAndServe(); err != nil { - utils.Logger.Err(fmt.Sprintf("<%s> error: <%s>", utils.RadiusAgent, err.Error())) - } - exitChan <- true -} - func startHTTPAgent(internalSMGChan, internalDispatcherSChan chan rpcclient.RpcClientConnection, server *utils.Server, filterSChan chan *engine.FilterS, dfltTenant string, exitChan chan bool) { filterS := <-filterSChan @@ -798,7 +762,8 @@ func main() { services.NewDNSAgent(), services.NewFreeswitchAgent(), services.NewKamailioAgent(), - services.NewAsteriskAgent(), + services.NewAsteriskAgent(), // partial reload + services.NewRadiusAgent(), // partial reload ) internalAttributeSChan := attrS.GetIntenternalChan() internalChargerSChan := chrS.GetIntenternalChan() @@ -855,10 +820,6 @@ func main() { go startDiameterAgent(internalSMGChan, internalDispatcherSChan, filterSChan, exitChan) } - if cfg.RadiusAgentCfg().Enabled { - go startRadiusAgent(internalSMGChan, internalDispatcherSChan, filterSChan, exitChan) - } - if len(cfg.HttpAgentCfg()) != 0 { go startHTTPAgent(internalSMGChan, internalDispatcherSChan, server, filterSChan, cfg.GeneralCfg().DefaultTenant, exitChan) diff --git a/config/config.go b/config/config.go index 11450910d..8929d4ff8 100755 --- a/config/config.go +++ b/config/config.go @@ -1570,6 +1570,7 @@ func (cfg *CGRConfig) reloadSection(section string) (err error) { } fallthrough case RA_JSN: + cfg.rldChans[RALS_JSN] <- struct{}{} if !fall { break } diff --git a/services/radiusagent.go b/services/radiusagent.go new file mode 100644 index 000000000..f73f4723d --- /dev/null +++ b/services/radiusagent.go @@ -0,0 +1,111 @@ +/* +Real-time Online/Offline Charging System (OCS) for Telecom & ISP environments +Copyright (C) ITsysCOM GmbH + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see +*/ + +package services + +import ( + "fmt" + "sync" + + "github.com/cgrates/cgrates/agents" + "github.com/cgrates/cgrates/servmanager" + "github.com/cgrates/cgrates/utils" + "github.com/cgrates/rpcclient" +) + +// NewRadiusAgent returns the Radius Agent +func NewRadiusAgent() servmanager.Service { + return new(RadiusAgent) +} + +// RadiusAgent implements Agent interface +type RadiusAgent struct { + sync.RWMutex + rad *agents.RadiusAgent +} + +// Start should handle the sercive start +func (rad *RadiusAgent) Start(sp servmanager.ServiceProvider, waitCache bool) (err error) { + if rad.IsRunning() { + return fmt.Errorf("service aleady running") + } + + rad.Lock() + defer rad.Unlock() + var smgConn rpcclient.RpcClientConnection + utils.Logger.Info("Starting Radius agent") + if smgConn, err = sp.NewConnection(utils.SessionS, sp.GetConfig().RadiusAgentCfg().SessionSConns); err != nil { + utils.Logger.Crit(fmt.Sprintf("<%s> Could not connect to %s: %s", + utils.RadiusAgent, utils.SessionS, err.Error())) + return + } + + if rad.rad, err = agents.NewRadiusAgent(sp.GetConfig(), sp.GetFilterS(), smgConn); err != nil { + utils.Logger.Err(fmt.Sprintf("<%s> error: <%s>", utils.RadiusAgent, err.Error())) + return + } + + go func() { + if err = rad.rad.ListenAndServe(); err != nil { + utils.Logger.Err(fmt.Sprintf("<%s> error: <%s>", utils.RadiusAgent, err.Error())) + } + sp.GetExitChan() <- true + }() + return +} + +// GetIntenternalChan returns the internal connection chanel +func (rad *RadiusAgent) GetIntenternalChan() (conn chan rpcclient.RpcClientConnection) { + return nil +} + +// Reload handles the change of config +func (rad *RadiusAgent) Reload(sp servmanager.ServiceProvider) (err error) { + var smgConn rpcclient.RpcClientConnection + if smgConn, err = sp.NewConnection(utils.SessionS, sp.GetConfig().RadiusAgentCfg().SessionSConns); err != nil { + utils.Logger.Crit(fmt.Sprintf("<%s> Could not connect to %s: %s", + utils.RadiusAgent, utils.SessionS, err.Error())) + return + } + rad.Lock() + defer rad.Unlock() + rad.rad.SetSessionSConnection(smgConn) + return // partial reload +} + +// Shutdown stops the service +func (rad *RadiusAgent) Shutdown() (err error) { + return // no shutdown for the momment +} + +// GetRPCInterface returns the interface to register for server +func (rad *RadiusAgent) GetRPCInterface() interface{} { + return rad.rad +} + +// IsRunning returns if the service is running +func (rad *RadiusAgent) IsRunning() bool { + rad.RLock() + defer rad.RUnlock() + return rad != nil && rad.rad != nil +} + +// ServiceName returns the service name +func (rad *RadiusAgent) ServiceName() string { + return utils.RadiusAgent +} diff --git a/servmanager/servmanager.go b/servmanager/servmanager.go index 2d02304ce..ac548e243 100644 --- a/servmanager/servmanager.go +++ b/servmanager/servmanager.go @@ -292,6 +292,9 @@ func (srvMngr *ServiceManager) StartServices() (err error) { if srvMngr.GetConfig().AsteriskAgentCfg().Enabled { go srvMngr.startService(utils.AsteriskAgent) } + if srvMngr.GetConfig().RadiusAgentCfg().Enabled { + go srvMngr.startService(utils.RadiusAgent) + } // startServer() return } @@ -384,6 +387,10 @@ func (srvMngr *ServiceManager) handleReload() { if err = srvMngr.reloadService(utils.AsteriskAgent, srvMngr.GetConfig().AsteriskAgentCfg().Enabled); err != nil { return } + case <-srvMngr.GetConfig().GetReloadChan(config.RA_JSN): + if err = srvMngr.reloadService(utils.RadiusAgent, srvMngr.GetConfig().RadiusAgentCfg().Enabled); err != nil { + return + } } // handle RPC server }