18 func (i *Integer) Read(r io.Reader) error {
19 return binary.Read(r, binary.BigEndian, i)
23 Protocol = "\x13BitTorrent protocol"
27 Choke MessageType = iota
41 Index, Begin, Length Integer
46 func (msg Message) MarshalBinary() (data []byte, err error) {
47 buf := &bytes.Buffer{}
52 err = buf.WriteByte(byte(msg.Type))
57 case Choke, Unchoke, Interested, NotInterested:
59 err = binary.Write(buf, binary.BigEndian, msg.Index)
61 for _, i := range []Integer{msg.Index, msg.Begin, msg.Length} {
62 err = binary.Write(buf, binary.BigEndian, i)
68 _, err = buf.Write(marshalBitfield(msg.Bitfield))
70 for _, i := range []Integer{msg.Index, msg.Begin} {
71 err = binary.Write(buf, binary.BigEndian, i)
76 n, err := buf.Write(msg.Piece)
80 if n != len(msg.Piece) {
84 err = fmt.Errorf("unknown message type: %s", msg.Type)
86 data = make([]byte, 4+buf.Len())
87 binary.BigEndian.PutUint32(data, uint32(buf.Len()))
88 if buf.Len() != copy(data[4:], buf.Bytes()) {
96 MaxLength Integer // TODO: Should this include the length header or not?
99 func (d *Decoder) Decode(msg *Message) (err error) {
101 err = binary.Read(d.R, binary.BigEndian, &length)
105 if length > d.MaxLength {
106 return errors.New("message too long")
108 r := bufio.NewReader(io.LimitReader(d.R, int64(length)))
110 written, _ := io.Copy(ioutil.Discard, r)
111 if written != 0 && err == nil {
112 err = fmt.Errorf("short read on message type %d, left %d bytes", msg.Type, written)
113 } else if err == io.EOF {
114 err = io.ErrUnexpectedEOF
121 msg.Keepalive = false
122 c, err := r.ReadByte()
126 msg.Type = MessageType(c)
128 case Choke, Unchoke, Interested, NotInterested:
131 err = msg.Index.Read(r)
132 case Request, Cancel:
133 for _, data := range []*Integer{&msg.Index, &msg.Begin, &msg.Length} {
140 b := make([]byte, length-1)
141 _, err = io.ReadFull(r, b)
142 msg.Bitfield = unmarshalBitfield(b)
144 for _, pi := range []*Integer{&msg.Index, &msg.Begin} {
153 msg.Piece, err = ioutil.ReadAll(r)
155 err = fmt.Errorf("unknown message type %#v", c)
162 func (b Bytes) MarshalBinary() ([]byte, error) {
166 func unmarshalBitfield(b []byte) (bf []bool) {
167 for _, c := range b {
168 for i := 7; i >= 0; i-- {
169 bf = append(bf, (c>>uint(i))&1 == 1)
175 func marshalBitfield(bf []bool) (b []byte) {
176 b = make([]byte, (len(bf)+7)/8)
177 for i, have := range bf {
182 c |= 1 << uint(7-i%8)