package webtorrent import ( "fmt" "net/http" "github.com/AlexxIT/go2rtc/pkg/webtorrent" "github.com/gorilla/websocket" ) var upgrader *websocket.Upgrader var hashes map[string]map[string]*websocket.Conn func tracker(w http.ResponseWriter, r *http.Request) { if upgrader == nil { upgrader = &websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 2028, } upgrader.CheckOrigin = func(r *http.Request) bool { return true } } ws, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Warn().Err(err).Send() return } defer ws.Close() for { var msg webtorrent.Message if err = ws.ReadJSON(&msg); err != nil { return } //log.Trace().Msgf("[webtorrent] message=%v", msg) if msg.InfoHash == "" || msg.PeerId == "" { continue } if hashes == nil { hashes = map[string]map[string]*websocket.Conn{} } // new or old client with offers clients := hashes[msg.InfoHash] if clients == nil { clients = map[string]*websocket.Conn{ msg.PeerId: ws, } hashes[msg.InfoHash] = clients } else { clients[msg.PeerId] = ws } switch { case msg.Offers != nil: // ask for ping raw := fmt.Sprintf( `{"action":"announce","interval":120,"info_hash":"%s","complete":0,"incomplete":1}`, msg.InfoHash, ) if err = ws.WriteMessage(websocket.TextMessage, []byte(raw)); err != nil { log.Warn().Err(err).Send() return } // skip if no offers (server) if len(msg.Offers) == 0 { continue } // get and check only first offer offer := msg.Offers[0] if offer.OfferId == "" || offer.Offer.Type != "offer" || offer.Offer.SDP == "" { continue } // send offer to all clients (one of them - server) raw = fmt.Sprintf( `{"action":"announce","info_hash":"%s","peer_id":"%s","offer_id":"%s","offer":{"type":"offer","sdp":"%s"}}`, msg.InfoHash, msg.PeerId, offer.OfferId, offer.Offer.SDP, ) for _, server := range clients { if server != ws { _ = server.WriteMessage(websocket.TextMessage, []byte(raw)) } } case msg.OfferId != "" && msg.ToPeerId != "" && msg.Answer != nil: ws1, ok := clients[msg.ToPeerId] if !ok { continue } raw := fmt.Sprintf( `{"action":"announce","info_hash":"%s","peer_id":"%s","offer_id":"%s","answer":{"type":"answer","sdp":"%s"}}`, msg.InfoHash, msg.PeerId, msg.OfferId, msg.Answer.SDP, ) _ = ws1.WriteMessage(websocket.TextMessage, []byte(raw)) } } }