DiameterAgent V1DisconnectSession implementation

This commit is contained in:
DanB
2019-01-03 15:50:25 +01:00
parent fe11d50173
commit b99312da48
2 changed files with 65 additions and 20 deletions

View File

@@ -165,13 +165,13 @@ func (da *DiameterAgent) handleMessage(c diam.Conn, m *diam.Message) {
if da.cgrCfg.DiameterAgentCfg().ASRTempalte != "" {
sessID, err := diamDP.FieldAsString([]string{"Session-Id"})
if err != nil {
utils.Logger.Err(
utils.Logger.Warning(
fmt.Sprintf("<%s> failed retrieving Session-Id err: %s, message: %s",
utils.DiameterAgent, err.Error(), m))
writeOnConn(c, diamErr)
}
// cache message data needed for building up the ASR
engine.Cache.Set(utils.CacheDiameterMessages, sessID, &diamMessageData{c, m, reqVars},
engine.Cache.Set(utils.CacheDiameterMessages, sessID, &diamMsgData{c, m, reqVars},
nil, false, utils.NonTransactional)
}
// handle MaxActiveReqs
@@ -376,8 +376,45 @@ func (da *DiameterAgent) Call(serviceMethod string, args interface{}, reply inte
// V1DisconnectSession is part of the sessions.SessionSClient
func (da *DiameterAgent) V1DisconnectSession(args utils.AttrDisconnectSession, reply *string) (err error) {
//m := NewMessage(cmd uint32, 0, appid, 0, 0, m.Dictionary())
return utils.ErrNotImplemented
ssID, has := args.EventStart[utils.OriginID]
if !has {
utils.Logger.Info(
fmt.Sprintf("<%s> cannot disconnect session, missing OriginID in event: %s",
utils.DiameterAgent, utils.ToJSON(args.EventStart)))
return utils.ErrMandatoryIeMissing
}
msg, has := engine.Cache.Get(utils.CacheDiameterMessages, ssID.(string))
if !has {
utils.Logger.Warning(
fmt.Sprintf("<%s> cannot retrieve message from cache with OriginID: <%s>",
utils.DiameterAgent, ssID))
return utils.ErrMandatoryIeMissing
}
dmd := msg.(*diamMsgData)
aReq := newAgentRequest(
newDADataProvider(dmd.c, dmd.m),
dmd.vars, nil, nil,
da.cgrCfg.GeneralCfg().DefaultTenant,
da.cgrCfg.GeneralCfg().DefaultTimezone, da.filterS)
nM, err := aReq.AsNavigableMap(da.cgrCfg.DiameterAgentCfg().Templates[da.cgrCfg.DiameterAgentCfg().ASRTempalte])
if err != nil {
utils.Logger.Warning(
fmt.Sprintf("<%s> cannot disconnect session with OriginID: <%s>, err: %s",
utils.DiameterAgent, ssID, err.Error()))
return utils.ErrServerError
}
m := diam.NewMessage(dmd.m.Header.CommandCode, 0, dmd.m.Header.ApplicationID, 0, 0, dmd.m.Dictionary())
if err = updateDiamMsgFromNavMap(m, nM, da.cgrCfg.GeneralCfg().DefaultTimezone); err != nil {
utils.Logger.Warning(
fmt.Sprintf("<%s> cannot disconnect session with OriginID: <%s>, err: %s",
utils.DiameterAgent, ssID, err.Error()))
return utils.ErrServerError
}
if err = writeOnConn(dmd.c, m); err != nil {
return utils.ErrServerError
}
*reply = utils.OK
return
}
// V1GetActiveSessionIDs is part of the sessions.SessionSClient

View File

@@ -266,11 +266,12 @@ func messageSetAVPsWithPath(m *diam.Message, pathStr []string,
}
// writeOnConn writes the message on connection, logs failures
func writeOnConn(c diam.Conn, m *diam.Message) {
if _, err := m.WriteTo(c); err != nil {
func writeOnConn(c diam.Conn, m *diam.Message) (err error) {
if _, err = m.WriteTo(c); err != nil {
utils.Logger.Warning(fmt.Sprintf("<%s> failed writing message to %s, err: %s, msg: %s",
utils.DiameterAgent, c.RemoteAddr(), err.Error(), m))
}
return
}
// newDADataProvider constructs a DataProvider for a diameter message
@@ -404,20 +405,14 @@ func (dP *diameterDP) FieldAsInterface(fldPath []string) (data interface{}, err
return
}
// diamAnswer builds up the answer to be sent back to the client
func diamAnswer(m *diam.Message, resCode uint32, errFlag bool,
rply *config.NavigableMap, tmz string) (a *diam.Message, err error) {
a = newDiamAnswer(m, resCode)
if errFlag {
a.Header.CommandFlags = diam.ErrorFlag
}
// updateDiamMsgFromNavMap will update the diameter message with items from navigable map
func updateDiamMsgFromNavMap(m *diam.Message, navMp *config.NavigableMap, tmz string) (err error) {
// write reply into message
pathIdx := make(map[string]int) // group items for same path
for _, val := range rply.Values() {
for _, val := range navMp.Values() {
nmItms, isNMItems := val.([]*config.NMItem)
if !isNMItems {
return nil, fmt.Errorf("cannot encode reply value: %s, err: not NMItems", utils.ToJSON(val))
return fmt.Errorf("cannot encode reply value: %s, err: not NMItems", utils.ToJSON(val))
}
// find out the first itm which is not an attribute
var itm *config.NMItem
@@ -441,20 +436,33 @@ func diamAnswer(m *diam.Message, resCode uint32, errFlag bool,
}
itmStr, err := utils.IfaceAsString(itm.Data)
if err != nil {
return nil, fmt.Errorf("cannot convert data: %+v to string, err: %s", itm.Data, err)
return fmt.Errorf("cannot convert data: %+v to string, err: %s", itm.Data, err)
}
var newBranch bool
if itm.Config != nil && itm.Config.NewBranch {
newBranch = true
}
if err = messageSetAVPsWithPath(a, itm.Path,
if err = messageSetAVPsWithPath(m, itm.Path,
itmStr, newBranch, tmz); err != nil {
return nil, fmt.Errorf("setting item with path: %+v got err: %s", itm.Path, err.Error())
return fmt.Errorf("setting item with path: %+v got err: %s", itm.Path, err.Error())
}
}
return
}
// diamAnswer builds up the answer to be sent back to the client
func diamAnswer(m *diam.Message, resCode uint32, errFlag bool,
rply *config.NavigableMap, tmz string) (a *diam.Message, err error) {
a = newDiamAnswer(m, resCode)
if errFlag {
a.Header.CommandFlags = diam.ErrorFlag
}
if err = updateDiamMsgFromNavMap(a, rply, tmz); err != nil {
return nil, err
}
return
}
// negDiamAnswer is used to return the negative answer we need previous to
func diamErr(m *diam.Message, resCode uint32,
reqVars map[string]interface{},
@@ -507,7 +515,7 @@ func newDiamAnswer(m *diam.Message, resCode uint32) *diam.Message {
}
// diamMessageData is cached when data is needed (ie. )
type diamMessageData struct {
type diamMsgData struct {
c diam.Conn
m *diam.Message
vars map[string]interface{}