How to perform dynamic unmarsahlling

99 views
Skip to first unread message

afriyie...@gmail.com

unread,
Sep 12, 2019, 4:33:27 AM9/12/19
to golang-nuts
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\n", 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\n", 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())
           }
        }
    }

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.

burak serdar

unread,
Sep 12, 2019, 11:14:02 AM9/12/19
to afriyie...@gmail.com, golang-nuts
On Thu, Sep 12, 2019 at 2:33 AM <afriyie...@gmail.com> wrote:
>
> 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.

HandleChallRequest is a subset of HandleDERRequest. How do you figure
out the received message is a HandleDERRequest? If it is done only by
the absence of fields, then you can simply unmarshal a
HandleDERRequest, check if certain fields are missing, and if so, copy
it to a HandleChallRequest.

Or, since HandleDERRequest has more fields, you can embed
HandleChallRequest into HandleDERRequest, and if certain fields are
missing, use only the HandleChallRequest portion of it.
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/ec15b55e-a927-4bc7-a8ea-cc9f172df506%40googlegroups.com.

Dimas Prawira

unread,
Sep 12, 2019, 11:22:44 AM9/12/19
to afriyie...@gmail.com, golang-nuts
Hi Abraham,

To perform dynamic unmarshal, you can use reflect package in Go.

May this reference give help : 

Thank you


Reply all
Reply to author
Forward
0 new messages