You've already forked torrent-client
mirror of
https://github.com/veggiedefender/torrent-client.git
synced 2025-11-06 09:29:16 +02:00
61 lines
1.2 KiB
Go
61 lines
1.2 KiB
Go
package handshake
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
)
|
|
|
|
// A Handshake is a sequence of bytes a peer uses to identify itself
|
|
type Handshake struct {
|
|
Pstr string
|
|
InfoHash [20]byte
|
|
PeerID [20]byte
|
|
}
|
|
|
|
// Serialize serializes the handshake to a buffer
|
|
func (h *Handshake) Serialize() []byte {
|
|
pstrlen := len(h.Pstr)
|
|
bufLen := 49 + pstrlen
|
|
buf := make([]byte, bufLen)
|
|
buf[0] = byte(pstrlen)
|
|
copy(buf[1:], h.Pstr)
|
|
// Leave 8 reserved bytes
|
|
copy(buf[1+pstrlen+8:], h.InfoHash[:])
|
|
copy(buf[1+pstrlen+8+20:], h.PeerID[:])
|
|
return buf
|
|
}
|
|
|
|
// Read parses a message from a stream. Returns `nil` on keep-alive message
|
|
func Read(r io.Reader) (*Handshake, error) {
|
|
lengthBuf := make([]byte, 1)
|
|
_, err := io.ReadFull(r, lengthBuf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pstrlen := int(lengthBuf[0])
|
|
|
|
if pstrlen == 0 {
|
|
err := errors.New("pstrlen cannot be 0")
|
|
return nil, err
|
|
}
|
|
|
|
handshakeBuf := make([]byte, 48+pstrlen)
|
|
_, err = io.ReadFull(r, handshakeBuf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var infoHash, peerID [20]byte
|
|
|
|
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
|
|
}
|