package message import ( proto "github.com/jbenet/go-ipfs/Godeps/_workspace/src/code.google.com/p/goprotobuf/proto" blocks "github.com/jbenet/go-ipfs/blocks" pb "github.com/jbenet/go-ipfs/exchange/bitswap/message/internal/pb" netmsg "github.com/jbenet/go-ipfs/net/message" nm "github.com/jbenet/go-ipfs/net/message" peer "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" ) // 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 type BitSwapMessage interface { // Wantlist returns a slice of unique keys that represent data wanted by // the sender. Wantlist() []u.Key // Blocks returns a slice of unique blocks Blocks() []blocks.Block // AddWanted adds the key to the Wantlist. // // Insertion order determines priority. That is, earlier insertions are // deemed higher priority than keys inserted later. // // t = 0, msg.AddWanted(A) // t = 1, msg.AddWanted(B) // // implies Priority(A) > Priority(B) AddWanted(u.Key) AddBlock(blocks.Block) Exportable } type Exportable interface { ToProto() *pb.Message ToNet(p peer.Peer) (nm.NetMessage, error) } type impl struct { existsInWantlist map[u.Key]struct{} // map to detect duplicates wantlist []u.Key // slice to preserve ordering blocks map[u.Key]blocks.Block // map to detect duplicates } func New() BitSwapMessage { return &impl{ blocks: make(map[u.Key]blocks.Block), existsInWantlist: make(map[u.Key]struct{}), wantlist: make([]u.Key, 0), } } func newMessageFromProto(pbm pb.Message) BitSwapMessage { m := New() for _, s := range pbm.GetWantlist() { m.AddWanted(u.Key(s)) } for _, d := range pbm.GetBlocks() { b := blocks.NewBlock(d) m.AddBlock(*b) } return m } func (m *impl) Wantlist() []u.Key { return m.wantlist } func (m *impl) Blocks() []blocks.Block { bs := make([]blocks.Block, 0) for _, block := range m.blocks { bs = append(bs, block) } return bs } func (m *impl) AddWanted(k u.Key) { _, exists := m.existsInWantlist[k] if exists { return } m.existsInWantlist[k] = struct{}{} m.wantlist = append(m.wantlist, k) } func (m *impl) AddBlock(b blocks.Block) { m.blocks[b.Key()] = b } func FromNet(nmsg netmsg.NetMessage) (BitSwapMessage, error) { pb := new(pb.Message) if err := proto.Unmarshal(nmsg.Data(), pb); err != nil { return nil, err } m := newMessageFromProto(*pb) return m, nil } func (m *impl) ToProto() *pb.Message { pb := new(pb.Message) 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 } func (m *impl) ToNet(p peer.Peer) (nm.NetMessage, error) { return nm.FromObject(p, m.ToProto()) }