wstracker.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. package torrent
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. netHttp "net/http"
  7. "net/url"
  8. "sync"
  9. "github.com/anacrolix/log"
  10. "github.com/gorilla/websocket"
  11. "github.com/pion/datachannel"
  12. "github.com/pion/webrtc/v3"
  13. "github.com/anacrolix/torrent/tracker"
  14. httpTracker "github.com/anacrolix/torrent/tracker/http"
  15. "github.com/anacrolix/torrent/webtorrent"
  16. )
  17. type websocketTrackerStatus struct {
  18. url url.URL
  19. tc *webtorrent.TrackerClient
  20. }
  21. func (me websocketTrackerStatus) statusLine() string {
  22. return fmt.Sprintf("%+v", me.tc.Stats())
  23. }
  24. func (me websocketTrackerStatus) URL() *url.URL {
  25. return &me.url
  26. }
  27. func (me websocketTrackerStatus) Stop() {
  28. }
  29. type refCountedWebtorrentTrackerClient struct {
  30. webtorrent.TrackerClient
  31. refCount int
  32. }
  33. type websocketTrackers struct {
  34. PeerId [20]byte
  35. Logger log.Logger
  36. GetAnnounceRequest func(event tracker.AnnounceEvent, infoHash [20]byte) (tracker.AnnounceRequest, error)
  37. OnConn func(datachannel.ReadWriteCloser, webtorrent.DataChannelContext)
  38. mu sync.Mutex
  39. clients map[string]*refCountedWebtorrentTrackerClient
  40. Proxy httpTracker.ProxyFunc
  41. DialContext func(ctx context.Context, network, addr string) (net.Conn, error)
  42. WebsocketTrackerHttpHeader func() netHttp.Header
  43. ICEServers []webrtc.ICEServer
  44. }
  45. func (me *websocketTrackers) Get(url string, infoHash [20]byte) (*webtorrent.TrackerClient, func()) {
  46. me.mu.Lock()
  47. defer me.mu.Unlock()
  48. value, ok := me.clients[url]
  49. if !ok {
  50. dialer := &websocket.Dialer{
  51. Proxy: me.Proxy,
  52. NetDialContext: me.DialContext,
  53. HandshakeTimeout: websocket.DefaultDialer.HandshakeTimeout,
  54. }
  55. value = &refCountedWebtorrentTrackerClient{
  56. TrackerClient: webtorrent.TrackerClient{
  57. Dialer: dialer,
  58. Url: url,
  59. GetAnnounceRequest: me.GetAnnounceRequest,
  60. PeerId: me.PeerId,
  61. OnConn: me.OnConn,
  62. Logger: me.Logger.WithText(
  63. func(m log.Msg) string {
  64. return fmt.Sprintf("tracker client for %q: %v", url, m)
  65. },
  66. ),
  67. WebsocketTrackerHttpHeader: me.WebsocketTrackerHttpHeader,
  68. ICEServers: me.ICEServers,
  69. },
  70. }
  71. value.TrackerClient.Start(func(err error) {
  72. if err != nil {
  73. me.Logger.Printf("error running tracker client for %q: %v", url, err)
  74. }
  75. })
  76. if me.clients == nil {
  77. me.clients = make(map[string]*refCountedWebtorrentTrackerClient)
  78. }
  79. me.clients[url] = value
  80. }
  81. value.refCount++
  82. return &value.TrackerClient, func() {
  83. me.mu.Lock()
  84. defer me.mu.Unlock()
  85. value.TrackerClient.CloseOffersForInfohash(infoHash)
  86. value.refCount--
  87. if value.refCount == 0 {
  88. value.TrackerClient.Close()
  89. delete(me.clients, url)
  90. }
  91. }
  92. }