From: Matt Joiner Date: Mon, 13 Apr 2020 04:31:39 +0000 (+1000) Subject: Tidy up the webtorrent package, remove buffer X-Git-Tag: v1.16.0~85^2~4 X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=e5fd9ede549a96e936b1692542b8753dfc1b3f90;p=btrtrc.git Tidy up the webtorrent package, remove buffer --- diff --git a/torrent.go b/torrent.go index a5c51bf8..731d4956 100644 --- a/torrent.go +++ b/torrent.go @@ -1322,7 +1322,7 @@ func (t *Torrent) startScrapingTracker(_url string) { return fmt.Sprintf("%q: %v", u.String(), m.Text()) }))} go func() { - err := wst.Client.Run(t.announceRequest(tracker.Started), u.String()) + err := wst.TrackerClient.Run(t.announceRequest(tracker.Started), u.String()) if err != nil { t.logger.WithValues(log.Error).Printf("error running websocket tracker announcer: %v", err) } diff --git a/webtorrent/buffer/buffer.go b/webtorrent/buffer/buffer.go deleted file mode 100644 index bac28abd..00000000 --- a/webtorrent/buffer/buffer.go +++ /dev/null @@ -1,68 +0,0 @@ -// Package buffer mirrors the Node.JS buffer type. -package buffer - -import ( - "crypto/rand" - "encoding/base64" - "encoding/hex" - "fmt" -) - -// Buffer mirrors the Node.JS Buffer type. -type Buffer struct { - b []byte -} - -// New creates a new buffer from b -func New(b []byte) *Buffer { - return &Buffer{b: b} -} - -// From creates a new buffer from a string -func From(s string) *Buffer { - return &Buffer{b: []byte(s)} -} - -// FromHex creates a new buffer from a hex string. -func FromHex(in string) (*Buffer, error) { - decoded, err := hex.DecodeString(in) - if err != nil { - return nil, fmt.Errorf("failed to decode hex: %v", err) - } - return &Buffer{b: decoded}, nil -} - -// ToStringBase64 turns the buffer into a base64 string. -func (b *Buffer) ToStringBase64() string { - return base64.StdEncoding.EncodeToString(b.b) -} - -// ToStringLatin1 turns the buffer into a string using -// Latin-1 supplement block and C0/C1 control codes. -func (b *Buffer) ToStringLatin1() string { - seq := []rune{} - for _, v := range b.b { - seq = append(seq, rune(v)) - } - return string(seq) -} - -// ToStringHex converts the buffer to a hex string -func (b *Buffer) ToStringHex() string { - return hex.EncodeToString(b.b) -} - -// RandomBytes returns securely generated random bytes. -// It will return an error if the system's secure random -// number generator fails to function correctly, in which -// case the caller should not continue. -func RandomBytes(n int) (*Buffer, error) { - b := make([]byte, n) - _, err := rand.Read(b) - // Note that err == nil only if we read len(b) bytes. - if err != nil { - return nil, err - } - - return New(b), nil -} diff --git a/webtorrent/client.go b/webtorrent/tracker_client.go similarity index 70% rename from webtorrent/client.go rename to webtorrent/tracker_client.go index 9d232d02..311b8cfe 100644 --- a/webtorrent/client.go +++ b/webtorrent/tracker_client.go @@ -1,6 +1,7 @@ package webtorrent import ( + "crypto/rand" "encoding/json" "fmt" "sync" @@ -8,14 +9,13 @@ import ( "github.com/anacrolix/log" "github.com/anacrolix/torrent/tracker" - "github.com/anacrolix/torrent/webtorrent/buffer" "github.com/gorilla/websocket" "github.com/pion/datachannel" "github.com/pion/webrtc/v2" ) // Client represents the webtorrent client -type Client struct { +type TrackerClient struct { lock sync.Mutex peerIDBinary string infoHashBinary string @@ -28,15 +28,7 @@ type Client struct { // outboundOffer represents an outstanding offer. type outboundOffer struct { originalOffer webrtc.SessionDescription - transport *Transport -} - -func binaryToJsonString(b []byte) string { - var seq []rune - for _, v := range b { - seq = append(seq, rune(v)) - } - return string(seq) + transport *transport } type DataChannelContext struct { @@ -47,8 +39,8 @@ type DataChannelContext struct { type onDataChannelOpen func(_ datachannel.ReadWriteCloser, dcc DataChannelContext) -func NewClient(peerId, infoHash [20]byte, onConn onDataChannelOpen, logger log.Logger) *Client { - return &Client{ +func NewClient(peerId, infoHash [20]byte, onConn onDataChannelOpen, logger log.Logger) *TrackerClient { + return &TrackerClient{ outboundOffers: make(map[string]outboundOffer), peerIDBinary: binaryToJsonString(peerId[:]), infoHashBinary: binaryToJsonString(infoHash[:]), @@ -57,7 +49,7 @@ func NewClient(peerId, infoHash [20]byte, onConn onDataChannelOpen, logger log.L } } -func (c *Client) Run(ar tracker.AnnounceRequest, url string) error { +func (c *TrackerClient) Run(ar tracker.AnnounceRequest, url string) error { t, _, err := websocket.DefaultDialer.Dial(url, nil) if err != nil { return fmt.Errorf("failed to dial tracker: %w", err) @@ -75,17 +67,18 @@ func (c *Client) Run(ar tracker.AnnounceRequest, url string) error { return c.trackerReadLoop() } -func (c *Client) announce(request tracker.AnnounceRequest) error { - transport, offer, err := NewTransport() +func (c *TrackerClient) announce(request tracker.AnnounceRequest) error { + transport, offer, err := newTransport() if err != nil { return fmt.Errorf("failed to create transport: %w", err) } - randOfferID, err := buffer.RandomBytes(20) + var randOfferId [20]byte + _, err = rand.Read(randOfferId[:]) if err != nil { return fmt.Errorf("failed to generate bytes: %w", err) } - offerIDBinary := randOfferID.ToStringLatin1() + offerIDBinary := binaryToJsonString(randOfferId[:]) c.lock.Lock() c.outboundOffers[offerIDBinary] = outboundOffer{ @@ -124,7 +117,7 @@ func (c *Client) announce(request tracker.AnnounceRequest) error { return nil } -func (c *Client) trackerReadLoop() error { +func (c *TrackerClient) trackerReadLoop() error { c.lock.Lock() tracker := c.tracker @@ -147,7 +140,7 @@ func (c *Client) trackerReadLoop() error { } switch { case ar.Offer != nil: - _, answer, err := NewTransportFromOffer(*ar.Offer, c.onConn, ar.OfferID) + _, answer, err := newTransportFromOffer(*ar.Offer, c.onConn, ar.OfferID) if err != nil { return fmt.Errorf("write AnnounceResponse: %w", err) } @@ -195,33 +188,3 @@ func (c *Client) trackerReadLoop() error { } } } - -type AnnounceRequest struct { - Numwant int `json:"numwant"` - Uploaded int `json:"uploaded"` - Downloaded int `json:"downloaded"` - Left int64 `json:"left"` - Event string `json:"event"` - Action string `json:"action"` - InfoHash string `json:"info_hash"` - PeerID string `json:"peer_id"` - Offers []Offer `json:"offers"` -} - -type Offer struct { - OfferID string `json:"offer_id"` - Offer webrtc.SessionDescription `json:"offer"` -} - -type AnnounceResponse struct { - InfoHash string `json:"info_hash"` - Action string `json:"action"` - Interval *int `json:"interval,omitempty"` - Complete *int `json:"complete,omitempty"` - Incomplete *int `json:"incomplete,omitempty"` - PeerID string `json:"peer_id,omitempty"` - ToPeerID string `json:"to_peer_id,omitempty"` - Answer *webrtc.SessionDescription `json:"answer,omitempty"` - Offer *webrtc.SessionDescription `json:"offer,omitempty"` - OfferID string `json:"offer_id,omitempty"` -} diff --git a/webtorrent/tracker_protocol.go b/webtorrent/tracker_protocol.go new file mode 100644 index 00000000..48c460b0 --- /dev/null +++ b/webtorrent/tracker_protocol.go @@ -0,0 +1,45 @@ +package webtorrent + +import ( + "github.com/pion/webrtc/v2" +) + +type AnnounceRequest struct { + Numwant int `json:"numwant"` + Uploaded int `json:"uploaded"` + Downloaded int `json:"downloaded"` + Left int64 `json:"left"` + Event string `json:"event"` + Action string `json:"action"` + InfoHash string `json:"info_hash"` + PeerID string `json:"peer_id"` + Offers []Offer `json:"offers"` +} + +type Offer struct { + OfferID string `json:"offer_id"` + Offer webrtc.SessionDescription `json:"offer"` +} + +type AnnounceResponse struct { + InfoHash string `json:"info_hash"` + Action string `json:"action"` + Interval *int `json:"interval,omitempty"` + Complete *int `json:"complete,omitempty"` + Incomplete *int `json:"incomplete,omitempty"` + PeerID string `json:"peer_id,omitempty"` + ToPeerID string `json:"to_peer_id,omitempty"` + Answer *webrtc.SessionDescription `json:"answer,omitempty"` + Offer *webrtc.SessionDescription `json:"offer,omitempty"` + OfferID string `json:"offer_id,omitempty"` +} + +// I wonder if this is a defacto standard way to decode bytes to JSON for webtorrent. I don't really +// care. +func binaryToJsonString(b []byte) string { + var seq []rune + for _, v := range b { + seq = append(seq, rune(v)) + } + return string(seq) +} diff --git a/webtorrent/transport.go b/webtorrent/transport.go index db2a94c9..5bdf99c0 100644 --- a/webtorrent/transport.go +++ b/webtorrent/transport.go @@ -12,8 +12,7 @@ import ( var ( api = func() *webrtc.API { - // Enable the detach API (since it's non-standard but more idiomatic) - // (This should be done once globally) + // Enable the detach API (since it's non-standard but more idiomatic). s := webrtc.SettingEngine{} s.DetachDataChannels() return webrtc.NewAPI(webrtc.WithSettingEngine(s)) @@ -28,15 +27,15 @@ func newPeerConnection() (*webrtc.PeerConnection, error) { return api.NewPeerConnection(config) } -type Transport struct { +type transport struct { pc *webrtc.PeerConnection dc *webrtc.DataChannel lock sync.Mutex } -// NewTransport creates a transport and returns a WebRTC offer to be announced -func NewTransport() (*Transport, webrtc.SessionDescription, error) { +// newTransport creates a transport and returns a WebRTC offer to be announced +func newTransport() (*transport, webrtc.SessionDescription, error) { peerConnection, err := newPeerConnection() if err != nil { return nil, webrtc.SessionDescription{}, fmt.Errorf("failed to peer connection: %v\n", err) @@ -61,13 +60,13 @@ func NewTransport() (*Transport, webrtc.SessionDescription, error) { return nil, webrtc.SessionDescription{}, fmt.Errorf("failed to set local description: %v\n", err) } - t := &Transport{pc: peerConnection, dc: dataChannel} + t := &transport{pc: peerConnection, dc: dataChannel} return t, offer, nil } -// NewTransportFromOffer creates a transport from a WebRTC offer and and returns a WebRTC answer to +// newTransportFromOffer creates a transport from a WebRTC offer and and returns a WebRTC answer to // be announced. -func NewTransportFromOffer(offer webrtc.SessionDescription, onOpen onDataChannelOpen, offerId string) (*Transport, webrtc.SessionDescription, error) { +func newTransportFromOffer(offer webrtc.SessionDescription, onOpen onDataChannelOpen, offerId string) (*transport, webrtc.SessionDescription, error) { peerConnection, err := newPeerConnection() if err != nil { return nil, webrtc.SessionDescription{}, fmt.Errorf("failed to peer connection: %v", err) @@ -76,7 +75,7 @@ func NewTransportFromOffer(offer webrtc.SessionDescription, onOpen onDataChannel fmt.Printf("ICE Connection State has changed: %s\n", connectionState.String()) }) - t := &Transport{pc: peerConnection} + t := &transport{pc: peerConnection} err = peerConnection.SetRemoteDescription(offer) if err != nil { @@ -104,7 +103,7 @@ func NewTransportFromOffer(offer webrtc.SessionDescription, onOpen onDataChannel } // SetAnswer sets the WebRTC answer -func (t *Transport) SetAnswer(answer webrtc.SessionDescription, onOpen func(datachannel.ReadWriteCloser)) error { +func (t *transport) SetAnswer(answer webrtc.SessionDescription, onOpen func(datachannel.ReadWriteCloser)) error { t.handleOpen(onOpen) err := t.pc.SetRemoteDescription(answer) @@ -114,7 +113,7 @@ func (t *Transport) SetAnswer(answer webrtc.SessionDescription, onOpen func(data return nil } -func (t *Transport) handleOpen(onOpen func(datachannel.ReadWriteCloser)) { +func (t *transport) handleOpen(onOpen func(datachannel.ReadWriteCloser)) { t.lock.Lock() dc := t.dc t.lock.Unlock() diff --git a/wstracker.go b/wstracker.go index 4001b73e..8cf66e86 100644 --- a/wstracker.go +++ b/wstracker.go @@ -9,7 +9,7 @@ import ( type websocketTracker struct { url url.URL - *webtorrent.Client + *webtorrent.TrackerClient } func (me websocketTracker) statusLine() string {