11 "github.com/anacrolix/log"
12 "github.com/gorilla/websocket"
13 "github.com/pion/datachannel"
14 "github.com/pion/webrtc/v3"
16 "github.com/anacrolix/torrent/tracker"
17 httpTracker "github.com/anacrolix/torrent/tracker/http"
18 "github.com/anacrolix/torrent/webtorrent"
21 type websocketTrackerStatus struct {
23 tc *webtorrent.TrackerClient
26 func (me websocketTrackerStatus) statusLine() string {
27 return fmt.Sprintf("%+v", me.tc.Stats())
30 func (me websocketTrackerStatus) URL() *url.URL {
34 type refCountedWebtorrentTrackerClient struct {
35 webtorrent.TrackerClient
39 type websocketTrackers struct {
42 GetAnnounceRequest func(event tracker.AnnounceEvent, infoHash [20]byte) (tracker.AnnounceRequest, error)
43 OnConn func(datachannel.ReadWriteCloser, webtorrent.DataChannelContext)
45 clients map[string]*refCountedWebtorrentTrackerClient
46 Proxy httpTracker.ProxyFunc
47 DialContext func(ctx context.Context, network, addr string) (net.Conn, error)
48 WebsocketTrackerHttpHeader func() netHttp.Header
49 ICEServers []webrtc.ICEServer
52 func (me *websocketTrackers) Get(url string, infoHash [20]byte) (*webtorrent.TrackerClient, func()) {
55 value, ok := me.clients[url]
57 dialer := &websocket.Dialer{Proxy: me.Proxy, NetDialContext: me.DialContext, HandshakeTimeout: websocket.DefaultDialer.HandshakeTimeout}
58 value = &refCountedWebtorrentTrackerClient{
59 TrackerClient: webtorrent.TrackerClient{
62 GetAnnounceRequest: me.GetAnnounceRequest,
65 Logger: me.Logger.WithText(func(m log.Msg) string {
66 return fmt.Sprintf("tracker client for %q: %v", url, m)
68 WebsocketTrackerHttpHeader: me.WebsocketTrackerHttpHeader,
69 ICEServers: me.ICEServers,
72 value.TrackerClient.Start(func(err error) {
74 me.Logger.Printf("error running tracker client for %q: %v", url, err)
77 if me.clients == nil {
78 me.clients = make(map[string]*refCountedWebtorrentTrackerClient)
80 me.clients[url] = value
83 return &value.TrackerClient, func() {
86 value.TrackerClient.CloseOffersForInfohash(infoHash)
88 if value.refCount == 0 {
89 value.TrackerClient.Close()
90 delete(me.clients, url)