aboutsummaryrefslogtreecommitdiff
path: root/peer/messages.go
blob: 02a379db5c3423627a3ef18373de4ac39e073f52 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package peer

import "io"

// Messages
const (
	Choke         = iota // choke: <len=0001><id=0>
	Unchoke              // unchoke: <len=0001><id=1>
	Interested           // interested: <len=0001><id=2>
	NotInterested        // not interested: <len=0001><id=3>
	Have                 // have: <len=0005><id=4><piece index>
	BitField             // bitfield: <len=0001+X><id=5><bitfield>
	Request              // request: <len=0013><id=6><index><begin><length>
	Piece                // piece: <len=0009+X><id=7><index><begin><block>
	Cancel               // cancel: <len=0013><id=8><index><begin><length>
	Port                 // port: <len=0003><id=9><listen-port> DHT
	_                    // keep-alive: <len=0000>
	_
	_
	Suggset
	HaveAll
	HaveNone
	Reject
	AllowedFast
	_
	_
	LTEPHandshake
)

const Proto = `BitTorrent protocol`

type Handshake struct {
	Proto    string
	Flags    [8]byte
	InfoHash [20]byte
	PeerID   [20]byte
}

func (h Handshake) Encode(w io.Writer) {
	Frame(w, []byte(h.Proto))
	w.Write(h.Flags[:])
	w.Write(h.InfoHash[:])
	w.Write(h.PeerID[:])
}

func DecodeHandshake(r io.Reader) (Handshake, bool) {
	var h Handshake
	h.Proto = string(Deframe(r))
	if h.Proto != Proto {
		return h, false
	}
	r.Read(h.Flags[:])
	r.Read(h.InfoHash[:])
	r.Read(h.PeerID[:])
	return h, true
}

func Frame(w io.Writer, b []byte) {
	l := len(b)
	w.Write([]byte{byte(l)})
	w.Write(b)
}

func Deframe(r io.Reader) []byte {
	l := make([]byte, 1)
	r.Read(l)
	if sz := int(l[0]); sz > 0 {
		b := make([]byte, sz)
		r.Read(b)
		return b
	}
	return nil
}