message.go 2.16 KB
Newer Older
1 2 3
package message

import (
4
	proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto"
5
	blocks "github.com/jbenet/go-ipfs/blocks"
6
	pb "github.com/jbenet/go-ipfs/exchange/bitswap/message/internal/pb"
7
	netmsg "github.com/jbenet/go-ipfs/net/message"
8 9 10 11 12
	nm "github.com/jbenet/go-ipfs/net/message"
	peer "github.com/jbenet/go-ipfs/peer"
	u "github.com/jbenet/go-ipfs/util"
)

13 14 15
// TODO move message.go into the bitswap package
// TODO move bs/msg/internal/pb to bs/internal/pb and rename pb package to bitswap_pb

16 17 18
type BitSwapMessage interface {
	Wantlist() []u.Key
	Blocks() []blocks.Block
19
	AddWanted(k u.Key)
20 21 22 23 24
	AppendBlock(b blocks.Block)
	Exportable
}

type Exportable interface {
25
	ToProto() *pb.Message
26
	ToNet(p peer.Peer) (nm.NetMessage, error)
27 28 29 30
}

// message wraps a proto message for convenience
type message struct {
31
	wantlist map[u.Key]struct{}
32
	blocks   []blocks.Block
33 34
}

35 36 37 38
func New() BitSwapMessage {
	return &message{
		wantlist: make(map[u.Key]struct{}),
	}
39 40
}

41
func newMessageFromProto(pbm pb.Message) BitSwapMessage {
42 43
	m := New()
	for _, s := range pbm.GetWantlist() {
44
		m.AddWanted(u.Key(s))
45 46
	}
	for _, d := range pbm.GetBlocks() {
47
		b := blocks.NewBlock(d)
48 49
		m.AppendBlock(*b)
	}
50
	return m
51 52
}

53 54
// TODO(brian): convert these into keys
func (m *message) Wantlist() []u.Key {
55 56 57 58 59
	wl := make([]u.Key, 0)
	for k, _ := range m.wantlist {
		wl = append(wl, k)
	}
	return wl
60 61 62 63
}

// TODO(brian): convert these into blocks
func (m *message) Blocks() []blocks.Block {
64
	return m.blocks
65 66
}

67
func (m *message) AddWanted(k u.Key) {
68
	m.wantlist[k] = struct{}{}
69 70 71
}

func (m *message) AppendBlock(b blocks.Block) {
72
	m.blocks = append(m.blocks, b)
73 74 75
}

func FromNet(nmsg netmsg.NetMessage) (BitSwapMessage, error) {
76
	pb := new(pb.Message)
77 78 79
	if err := proto.Unmarshal(nmsg.Data(), pb); err != nil {
		return nil, err
	}
80
	m := newMessageFromProto(*pb)
81
	return m, nil
82 83
}

84 85
func (m *message) ToProto() *pb.Message {
	pb := new(pb.Message)
86 87 88 89 90 91 92
	for _, k := range m.Wantlist() {
		pb.Wantlist = append(pb.Wantlist, string(k))
	}
	for _, b := range m.Blocks() {
		pb.Blocks = append(pb.Blocks, b.Data)
	}
	return pb
93 94
}

95
func (m *message) ToNet(p peer.Peer) (nm.NetMessage, error) {
96 97
	return nm.FromObject(p, m.ToProto())
}