2019-12-24 10:39:22 -05:00
|
|
|
package handshake
|
2019-12-22 16:03:38 -05:00
|
|
|
|
|
|
|
|
import (
|
2020-01-02 10:30:30 -05:00
|
|
|
"fmt"
|
2019-12-22 16:03:38 -05:00
|
|
|
"io"
|
|
|
|
|
)
|
|
|
|
|
|
2020-01-02 12:31:41 -05:00
|
|
|
// A Handshake is a special message that a peer uses to identify itself
|
2019-12-22 16:03:38 -05:00
|
|
|
type Handshake struct {
|
|
|
|
|
Pstr string
|
|
|
|
|
InfoHash [20]byte
|
2019-12-22 17:43:39 -05:00
|
|
|
PeerID [20]byte
|
2019-12-22 16:03:38 -05:00
|
|
|
}
|
|
|
|
|
|
2019-12-24 11:05:22 -05:00
|
|
|
// New creates a new handshake with the standard pstr
|
|
|
|
|
func New(infoHash, peerID [20]byte) *Handshake {
|
|
|
|
|
return &Handshake{
|
|
|
|
|
Pstr: "BitTorrent protocol",
|
|
|
|
|
InfoHash: infoHash,
|
|
|
|
|
PeerID: peerID,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-22 16:03:38 -05:00
|
|
|
// Serialize serializes the handshake to a buffer
|
|
|
|
|
func (h *Handshake) Serialize() []byte {
|
2020-01-12 09:17:19 -05:00
|
|
|
buf := make([]byte, len(h.Pstr)+49)
|
|
|
|
|
buf[0] = byte(len(h.Pstr))
|
|
|
|
|
curr := 1
|
|
|
|
|
curr += copy(buf[curr:], h.Pstr)
|
|
|
|
|
curr += copy(buf[curr:], make([]byte, 8)) // 8 reserved bytes
|
|
|
|
|
curr += copy(buf[curr:], h.InfoHash[:])
|
|
|
|
|
curr += copy(buf[curr:], h.PeerID[:])
|
2019-12-22 16:03:38 -05:00
|
|
|
return buf
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-02 12:31:41 -05:00
|
|
|
// Read parses a handshake from a stream
|
2020-01-02 19:36:25 -05:00
|
|
|
func Read(r io.Reader) (*Handshake, error) {
|
2019-12-22 16:03:38 -05:00
|
|
|
lengthBuf := make([]byte, 1)
|
|
|
|
|
_, err := io.ReadFull(r, lengthBuf)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
pstrlen := int(lengthBuf[0])
|
|
|
|
|
|
|
|
|
|
if pstrlen == 0 {
|
2020-01-02 10:30:30 -05:00
|
|
|
err := fmt.Errorf("pstrlen cannot be 0")
|
2019-12-22 16:03:38 -05:00
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
handshakeBuf := make([]byte, 48+pstrlen)
|
|
|
|
|
_, err = io.ReadFull(r, handshakeBuf)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-22 17:43:39 -05:00
|
|
|
var infoHash, peerID [20]byte
|
2019-12-22 16:03:38 -05:00
|
|
|
|
|
|
|
|
copy(infoHash[:], handshakeBuf[pstrlen+8:pstrlen+8+20])
|
|
|
|
|
copy(peerID[:], handshakeBuf[pstrlen+8+20:])
|
|
|
|
|
|
|
|
|
|
h := Handshake{
|
|
|
|
|
Pstr: string(handshakeBuf[0:pstrlen]),
|
|
|
|
|
InfoHash: infoHash,
|
|
|
|
|
PeerID: peerID,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &h, nil
|
|
|
|
|
}
|