doucong1992 2019-09-12 07:32
浏览 37

如何执行动态解组

Can anyone help me perform dynamic unmarshalling depending on the type of messages received from a diameter client. In the code below, I have to two structures which represent two different messages received by a diameter server. I would like to modify the current code which unmarshals the request to the struct var req HandleDERRequest such that the unmarshalling is done dynamically either to the var req HandleDERRequest or var challreq HandleChallRequest, depending on the received message that matches a particular structure. I have tried to implement with the code below but it not working as it should. All the answers are being return at the same time and this is not what am expecting.

func HandleDER(settings sm.Settings) diam.HandlerFunc {

    // If received AVP messages are of this struct format, Unmarshal message to this structure

    type HandleDERRequest struct {
        SessionID         datatype.UTF8String       `avp:"Session-Id"`
        OriginHost        datatype.DiameterIdentity `avp:"Origin-Host"`
        OriginRealm       datatype.DiameterIdentity `avp:"Origin-Realm"`
        DestinationHost   datatype.DiameterIdentity `avp:"Destination-Host"`
        DestinationRealm  datatype.DiameterIdentity `avp:"Destination-Realm"`
        UserName          datatype.UTF8String       `avp:"User-Name"`
        AuthSessionState  datatype.Enumerated       `avp:"Auth-Session-State"`
        AuthApplicationID datatype.Unsigned32       `avp:"Auth-Application-Id"`
        AuthRequestType   datatype.Enumerated       `avp:"Auth-Request-Type"`
        EAPPayload        datatype.OctetString      `avp:"EAP-Payload"`
        RATType           datatype.Enumerated       `avp:"RAT-Type"`
        ANID              datatype.UTF8String       `avp:"ANID"`
    }

    // If received AVP messages are of this struct format, Unmarshal message to this structure

    type HandleChallRequest struct {
        SessionID        datatype.UTF8String       `avp:"Session-Id"`
        OriginHost       datatype.DiameterIdentity `avp:"Origin-Host"`
        OriginRealm      datatype.DiameterIdentity `avp:"Origin-Realm"`
        DestinationHost  datatype.DiameterIdentity `avp:"Destination-Host"`
        DestinationRealm datatype.DiameterIdentity `avp:"Destination-Realm"`
        EAPPayload       datatype.OctetString      `avp:"EAP-Payload"`
    }

    return func(c diam.Conn, m *diam.Message) {

        var err error = nil
        var req HandleDERRequest

        var code uint32 = diam.Success
        err = m.Unmarshal(&req)
        if err != nil {
            err = fmt.Errorf("Unmarshal failed: %s", err)
            code = diam.UnableToComply
            log.Printf("Invalid DER(%d): %s
", code, err.Error())
        }
        a := m.Answer(code)
        a.NewAVP(avp.SessionID, avp.Mbit, 0, req.SessionID)
        a.NewAVP(avp.OriginHost, avp.Mbit, 0, req.DestinationHost)
        a.NewAVP(avp.OriginRealm, avp.Mbit, 0, req.DestinationRealm)
        a.NewAVP(avp.OriginStateID, avp.Mbit, 0, settings.OriginStateID)
        _, err = AKA_Challenge_Request(settings, c, a)
        if err != nil {
            log.Printf("Failed to send AAA challenge request: %s", err.Error())
        }

        var challreq HandleChallageRequest
        err = m.Unmarshal(&challreq)
        if err != nil {
            err = fmt.Errorf("Unmarshal failed: %s", err)
            code = diam.UnableToComply
            log.Printf("Invalid DER(%d): %s
", code, err.Error())
        }
        a = m.Answer(code)
        a.NewAVP(avp.SessionID, avp.Mbit, 0, req.SessionID)
        a.NewAVP(avp.OriginHost, avp.Mbit, 0, req.DestinationHost)
        a.NewAVP(avp.OriginRealm, avp.Mbit, 0, req.DestinationRealm)
        a.NewAVP(avp.OriginStateID, avp.Mbit, 0, settings.OriginStateID)
        _, err = AKA_Success_Notification(settings, c, a)
        if err != nil {
           log.Printf("Failed to send Success Notification: %s", err.Error())
       }
    }
}
func AKA_Challenge_Request(settings sm.Settings, w io.Writer, m *diam.Message) (n int64, err error) {
    PayloadSlice := []byte(`RAND, AUTHN, MAC, RESULT_ID`)
    m.NewAVP(avp.EAPPayload, avp.Mbit, 0, datatype.OctetString(PayloadSlice))
    return m.WriteTo(w)
}

func AKA_Success_Notification(settings sm.Settings, w io.Writer, m *diam.Message) (n int64, err error) {
    EAPSlice := []byte(`EAP_Success`)
    MSKSlice := []byte(`EAP-Master-Session-Key`)
    m.NewAVP(avp.EAPPayload, avp.Mbit, 0, datatype.OctetString(EAPSlice))
    m.NewAVP(avp.EAPMasterSessionKey, avp.Mbit, 0, datatype.OctetString(MSKSlice))
    return m.WriteTo(w)
}

I know there should be an if condition of the return function but I don't know how to start. Please any idea about how to go about it.

  • 写回答

1条回答 默认 最新

  • dongmuzhan4705 2019-09-12 08:46
    关注

    I would say that there is no need for the HandleChallRequest type at this point. If I have read the fields correctly both types have the same base attributes but the HandleDERRequest type has more, can these not just be nil values in the unmarshalled type ?

    You could then either do some kind of nil check to ascertain one data set from the other, or more preferred would be create an interface that has all the fields and a common set of methods so that you can then create two types that implement this interface and the choice becomes which one to create.

    Edit 1.

    Sorry again if I am missing the point but I still don't see the need for the different types, it seems to me that they are just data containers, with different data.

    Here is what I was thinking in terms of a single data type.

    func HandleDER(settings sm.Settings) diam.HandlerFunc {
    
    // If received AVP messages are of this struct format, Unmarshal message to this structure
    
    type HandleRequest struct {
        SessionID         datatype.UTF8String       `avp:"Session-Id"`
        OriginHost        datatype.DiameterIdentity `avp:"Origin-Host"`
        OriginRealm       datatype.DiameterIdentity `avp:"Origin-Realm"`
        DestinationHost   datatype.DiameterIdentity `avp:"Destination-Host"`
        DestinationRealm  datatype.DiameterIdentity `avp:"Destination-Realm"`
        UserName          datatype.UTF8String       `avp:"User-Name"`
        AuthSessionState  datatype.Enumerated       `avp:"Auth-Session-State"`
        AuthApplicationID datatype.Unsigned32       `avp:"Auth-Application-Id"`
        AuthRequestType   datatype.Enumerated       `avp:"Auth-Request-Type"`
        EAPPayload        datatype.OctetString      `avp:"EAP-Payload"`
        RATType           datatype.Enumerated       `avp:"RAT-Type"`
        ANID              datatype.UTF8String       `avp:"ANID"`
    }
    
    // If received AVP messages are of this struct format, Unmarshal message to this structure
    
    return func(c diam.Conn, m *diam.Message) {
    
        var err error = nil
        var req HandleRequest
    
        var code uint32 = diam.Success
    
        err = m.Unmarshal(&req)
        if err != nil {
            err = fmt.Errorf("Unmarshal failed: %s", err)
            code = diam.UnableToComply
            log.Printf("Invalid DER(%d): %s
    ", code, err.Error())
        }
        a := m.Answer(code)
        a.NewAVP(avp.SessionID, avp.Mbit, 0, req.SessionID)
        a.NewAVP(avp.OriginHost, avp.Mbit, 0, req.DestinationHost)
        a.NewAVP(avp.OriginRealm, avp.Mbit, 0, req.DestinationRealm)
        a.NewAVP(avp.OriginStateID, avp.Mbit, 0, settings.OriginStateID)
    
        if ("messagetype" == "first message type") {
            _, err = AKA_Challenge_Request(settings, c, a)
            if err != nil {
                log.Printf("Failed to send AAA challenge request: %s", err.Error())
            }
        } else {
            _, err = AKA_Success_Notification(settings, c, a)
            if err != nil {
                log.Printf("Failed to send Success Notification: %s", err.Error())
            }
        }
    }
    

    }

    评论

报告相同问题?

悬赏问题

  • ¥15 制裁名单20240508芯片厂商
  • ¥20 易康econgnition精度验证
  • ¥15 线程问题判断多次进入
  • ¥15 msix packaging tool打包问题
  • ¥28 微信小程序开发页面布局没问题,真机调试的时候页面布局就乱了
  • ¥15 python的qt5界面
  • ¥15 无线电能传输系统MATLAB仿真问题
  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接