Files
gopeed/protocol/bt/peer/message/message.go
T
2020-02-25 14:22:17 +08:00

97 lines
1.8 KiB
Go

package message
import (
"encoding/binary"
)
// message ID
type ID byte
const (
IdChoke ID = iota
IdUnchoke
IdInterested
IdNotinterested
IdHave
IdBitfield
IdRequest
IdPiece
IdCancel
)
/*type Message struct {
Length uint32
ID MessageID
Payload []byte
}*/
type Message struct {
Length uint32
ID ID
}
func (msg *Message) Encode() []byte {
buf := make([]byte, 5)
binary.BigEndian.PutUint32(buf, msg.Length)
buf[4] = byte(msg.ID)
return buf
}
func (msg *Message) Decode(buf []byte) {
msg.Length = binary.BigEndian.Uint32(buf)
msg.ID = ID(buf[4])
}
type Serialize interface {
Encode() []byte
Decode(buf []byte) Serialize
}
/*func NewMessage(id MessageID, payload []byte) *Message {
message := &Message{ID: id, Payload: payload}
if id == Keepalive {
message.Length = 0
} else {
message.Length = uint32(len(payload) + 1)
}
return message
}
func (msg *Message) Encode() []byte {
if msg.ID == Keepalive {
return make([]byte, 4)
} else {
buf := make([]byte, 5+len(msg.Payload))
binary.BigEndian.PutUint32(buf, msg.Length)
buf[4] = byte(msg.ID)
copy(buf[5:], msg.Payload[:])
return buf
}
}
func (msg *Message) Decode(buf []byte) {
msg.Length = binary.BigEndian.Uint32(buf)
if msg.Length == 0 {
msg.ID = -1
} else {
msg.ID = MessageID(buf[4])
if msg.Length > 4 {
msg.Payload = buf[5:]
}
}
}*/
// Message protocol
// Length prefix| message ID | Payload
// 4-byte | 1-byte | remaining bytes
// 100 | 5 | 99-bytes
// https://wiki.theory.org/index.php/BitTorrentSpecification#Messages
func SplitMessage(data []byte, atEOF bool) (advance int, token []byte, err error) {
if !atEOF && len(data) > 4 {
length := int(binary.BigEndian.Uint32(data))
if len(data)-4 >= length {
return length + 4, data[:length+4], nil
}
}
return
}