Skip to content
This repository has been archived by the owner on Sep 6, 2022. It is now read-only.

Unable to marshal / unmarshal AddrInfo within my struct #176

Open
pocockn opened this issue Feb 10, 2021 · 4 comments
Open

Unable to marshal / unmarshal AddrInfo within my struct #176

pocockn opened this issue Feb 10, 2021 · 4 comments
Assignees

Comments

@pocockn
Copy link

pocockn commented Feb 10, 2021

I need to unicast messages to other peers on my network. I want to store the AddrInfo struct on my message so I have the nodes addr who unicast me so I can send a response back.

func init() {
    gob.Register(&Message{})
}

// Message stores a type of message and a body.
// The message is the data that gets passed between nodes when they communicate.
type Message struct {
    ID         string           `json:"id"`
    Body       []byte           `json:"body"`        // the actual payload.
    OriginNode peer.AddrInfo    `json:"origin_node"` // the node that sent the message
}

// NewMessage builds up a new message.
func NewMessage(b []byte, o peer.AddrInfo) Message {
    return Message{
        ID:        uuid.New().String(),
        Body:      b,
        OriginNode: o,
    }
}

// Marshal takes a node message and marshals it into an array of bytes.
func (m Message) Marshal() []byte {
    var buf bytes.Buffer

    enc := gob.NewEncoder(&buf)

    if err := enc.Encode(m); err != nil {
        zap.S().Fatal(err)
    }

    return buf.Bytes()
}

// UnmarshalMessage takes a slice of bytes and a returns a message struct.
func UnmarshalMessage(input []byte) (Message, error) {
    msg := Message{}
    buf := bytes.NewBuffer(input)
    dec := gob.NewDecoder(buf)

    if err := dec.Decode(&msg); err != nil {
        return Message{}, err
    }

    return msg, nil
}

When I marshal my message struct and then attempt to unmarshal I receive the following error:

panic: interface conversion: interface is nil, not encoding.BinaryUnmarshaler [recovered]
panic: interface conversion: interface is nil, not encoding.BinaryUnmarshaler
UnmarshalMessage(0xc0001c7200, 0x454, 0x480, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, .

Is there something I need to do to be able to marshal and unmarshal my struct that contains the peer.AddrInfo ?

@aarshkshah1992
Copy link
Contributor

cc @Stebalien @marten-seemann

@marten-seemann
Copy link
Contributor

This seems to be a problem with encoding/gob, not in our stack. If I just use encoding/json everything works fine:

// Message stores a type of message and a body.
// The message is the data that gets passed between nodes when they communicate.
type Message struct {
	ID         string        `json:"id"`
	Body       []byte        `json:"body"`        // the actual payload.
	OriginNode peer.AddrInfo `json:"origin_node"` // the node that sent the message
}

// NewMessage builds up a new message.
func NewMessage(b []byte, o peer.AddrInfo) Message {
	return Message{
		ID:         "identifier",
		Body:       b,
		OriginNode: o,
	}
}

// Marshal takes a node message and marshals it into an array of bytes.
func (m Message) Marshal() ([]byte, error) {
	return json.Marshal(m)
}

// UnmarshalMessage takes a slice of bytes and a returns a message struct.
func UnmarshalMessage(input []byte) (Message, error) {
	msg := Message{}
	return msg, json.Unmarshal(input, &msg)
}

I'm not really familiar with encoding/gob to be honest, but here's the relevant part of the stack trace:

panic(0x131e400, 0xc00009de60)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/runtime/panic.go:969 +0x1b9
encoding/gob.catchError(0xc00012c0f0)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/error.go:38 +0x85
panic(0x131e400, 0xc00009de60)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/runtime/panic.go:969 +0x1b9
encoding/gob.(*Decoder).decodeGobDecoder(0xc00012c080, 0xc0000cdcc0, 0xc0000b1760, 0x1342be0, 0xc000099fb0, 0x194)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decode.go:736 +0x1fd
encoding/gob.(*Decoder).gobDecodeOpFor.func1(0xc0001481c0, 0xc0000b1760, 0x1342be0, 0xc000099fb0, 0x194)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decode.go:960 +0x7a
encoding/gob.(*Decoder).decodeArrayHelper(0xc00012c080, 0xc0000b1760, 0x1303b60, 0xc0000e4268, 0x197, 0xc0000b1960, 0x1, 0x14df3e0, 0xc000099fa0, 0x0)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decode.go:530 +0x179
encoding/gob.(*Decoder).decodeSlice(0xc00012c080, 0xc0000b1760, 0x1303b60, 0xc0000e4268, 0x197, 0xc0000b1960, 0x14df3e0, 0xc000099fa0, 0x0)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decode.go:630 +0x23c
encoding/gob.(*Decoder).decOpFor.func3(0xc0000ce8f8, 0xc0000b1760, 0x1303b60, 0xc0000e4268, 0x197)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decode.go:848 +0x78
encoding/gob.(*Decoder).decodeStruct(0xc00012c080, 0xc0000b1920, 0x133a2e0, 0xc0000e4258, 0x199)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decode.go:471 +0xe6
encoding/gob.(*Decoder).decOpFor.func4(0xc0000bc800, 0xc0000b1740, 0x133a2e0, 0xc0000e4258, 0x199)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decode.go:860 +0x54
encoding/gob.(*Decoder).decodeStruct(0xc00012c080, 0xc0000b1900, 0x133fda0, 0xc0000e4230, 0x199)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decode.go:471 +0xe6
encoding/gob.(*Decoder).decodeValue(0xc00012c080, 0x41, 0x1316d40, 0xc0000e4230, 0x16)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decode.go:1205 +0x2c5
encoding/gob.(*Decoder).DecodeValue(0xc00012c080, 0x1316d40, 0xc0000e4230, 0x16, 0x0, 0x0)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decoder.go:213 +0x146
encoding/gob.(*Decoder).Decode(0xc00012c080, 0x1316d40, 0xc0000e4230, 0xc000099c40, 0x1)
	/usr/local/Cellar/go/1.15.7_1/libexec/src/encoding/gob/decoder.go:188 +0x173
github.com/libp2p/go-libp2p-core/cmd.UnmarshalMessage(0xc00013e000, 0xd2, 0x17c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)

@Stebalien
Copy link
Member

It looks like we need to implement BinaryUnmarshal.

@Stebalien
Copy link
Member

But I'm not sure how to actually do this unless we want to define a custom "binary" format for address info objects.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants