10 "github.com/pkg/errors"
16 MaxLength Integer // TODO: Should this include the length header or not?
19 // io.EOF is returned if the source terminates cleanly on a message boundary.
20 func (d *Decoder) Decode(msg *Message) (err error) {
22 err = length.Read(d.R)
24 return fmt.Errorf("reading message length: %w", err)
26 if length > d.MaxLength {
27 return errors.New("message too long")
34 readByte := func() (byte, error) {
42 msg.Type = MessageType(c)
44 case Choke, Unchoke, Interested, NotInterested, HaveAll, HaveNone:
45 case Have, AllowedFast, Suggest:
47 err = msg.Index.Read(r)
48 case Request, Cancel, Reject:
49 for _, data := range []*Integer{&msg.Index, &msg.Begin, &msg.Length} {
57 b := make([]byte, length)
58 _, err = io.ReadFull(r, b)
60 msg.Bitfield = unmarshalBitfield(b)
62 for _, pi := range []*Integer{&msg.Index, &msg.Begin} {
69 dataLen := int64(length)
70 msg.Piece = *d.Pool.Get().(*[]byte)
71 if int64(cap(msg.Piece)) < dataLen {
72 return errors.New("piece data longer than expected")
74 msg.Piece = msg.Piece[:dataLen]
75 _, err := io.ReadFull(r, msg.Piece)
77 return fmt.Errorf("reading piece data: %w", err)
86 msg.ExtendedID = ExtensionNumber(b)
87 msg.ExtendedPayload = make([]byte, length)
88 _, err = io.ReadFull(r, msg.ExtendedPayload)
90 err = io.ErrUnexpectedEOF
94 err = binary.Read(r, binary.BigEndian, &msg.Port)
97 err = fmt.Errorf("unknown message type %#v", c)
99 if err == nil && length != 0 {
100 err = fmt.Errorf("%v unused bytes in message type %v", length, msg.Type)
105 func readByte(r io.Reader) (b byte, err error) {
107 n, err := r.Read(arr[:])
119 func unmarshalBitfield(b []byte) (bf []bool) {
120 for _, c := range b {
121 for i := 7; i >= 0; i-- {
122 bf = append(bf, (c>>uint(i))&1 == 1)