10 "github.com/pkg/errors"
15 // This must return *[]byte where the slices can fit data for piece messages. I think we store
16 // *[]byte in the pool to avoid an extra allocation every time we put the slice back into the
17 // pool. The chunk size should not change for the life of the decoder.
19 MaxLength Integer // TODO: Should this include the length header or not?
22 // io.EOF is returned if the source terminates cleanly on a message boundary.
23 func (d *Decoder) Decode(msg *Message) (err error) {
25 err = length.Read(d.R)
27 return fmt.Errorf("reading message length: %w", err)
29 if length > d.MaxLength {
30 return errors.New("message too long")
37 readByte := func() (byte, error) {
41 // From this point onwards, EOF is unexpected
44 err = io.ErrUnexpectedEOF
51 msg.Type = MessageType(c)
52 // Can return directly in cases when err is not nil, or length is known to be zero.
54 case Choke, Unchoke, Interested, NotInterested, HaveAll, HaveNone:
55 case Have, AllowedFast, Suggest:
57 err = msg.Index.Read(r)
58 case Request, Cancel, Reject:
59 for _, data := range []*Integer{&msg.Index, &msg.Begin, &msg.Length} {
67 b := make([]byte, length)
68 _, err = io.ReadFull(r, b)
70 msg.Bitfield = unmarshalBitfield(b)
73 for _, pi := range []*Integer{&msg.Index, &msg.Begin} {
80 dataLen := int64(length)
82 msg.Piece = make([]byte, dataLen)
84 msg.Piece = *d.Pool.Get().(*[]byte)
85 if int64(cap(msg.Piece)) < dataLen {
86 return errors.New("piece data longer than expected")
88 msg.Piece = msg.Piece[:dataLen]
90 _, err = io.ReadFull(r, msg.Piece)
99 msg.ExtendedID = ExtensionNumber(b)
100 msg.ExtendedPayload = make([]byte, length)
101 _, err = io.ReadFull(r, msg.ExtendedPayload)
105 err = binary.Read(r, binary.BigEndian, &msg.Port)
108 err = fmt.Errorf("unknown message type %#v", c)
110 if err == nil && length != 0 {
111 err = fmt.Errorf("%v unused bytes in message type %v", length, msg.Type)
116 func readByte(r io.Reader) (b byte, err error) {
118 n, err := r.Read(arr[:])
130 func unmarshalBitfield(b []byte) (bf []bool) {
131 for _, c := range b {
132 for i := 7; i >= 0; i-- {
133 bf = append(bf, (c>>uint(i))&1 == 1)