tracker/trackerserver/announce.go (92 lines of code) (raw):

// Copyright (c) 2016-2019 Uber Technologies, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package trackerserver import ( "encoding/json" "fmt" "net/http" "github.com/uber/kraken/core" "github.com/uber/kraken/tracker/announceclient" "github.com/uber/kraken/utils/errutil" "github.com/uber/kraken/utils/handler" "github.com/uber/kraken/utils/httputil" "github.com/uber/kraken/utils/log" ) func (s *Server) announceHandlerV1(w http.ResponseWriter, r *http.Request) error { req := new(announceclient.Request) if err := json.NewDecoder(r.Body).Decode(req); err != nil { return handler.Errorf("json decode request: %s", err) } d, err := req.GetDigest() if err != nil { return handler.Errorf("get request digest: %s", err) } resp, err := s.announce(d, req.InfoHash, req.Peer) if err != nil { return err } if err := json.NewEncoder(w).Encode(resp); err != nil { return handler.Errorf("json encode response: %s", err) } return nil } func (s *Server) announceHandlerV2(w http.ResponseWriter, r *http.Request) error { infohash, err := httputil.ParseParam(r, "infohash") if err != nil { return err } h, err := core.NewInfoHashFromHex(infohash) if err != nil { return fmt.Errorf("parse infohash: %s", err) } req := new(announceclient.Request) if err := json.NewDecoder(r.Body).Decode(req); err != nil { return handler.Errorf("json decode request: %s", err) } d, err := req.GetDigest() if err != nil { return handler.Errorf("get request digest: %s", err) } resp, err := s.announce(d, h, req.Peer) if err != nil { return err } if err := json.NewEncoder(w).Encode(resp); err != nil { return handler.Errorf("json encode response: %s", err) } return nil } func (s *Server) announce( d core.Digest, h core.InfoHash, peer *core.PeerInfo) (*announceclient.Response, error) { if err := s.peerStore.UpdatePeer(h, peer); err != nil { log.With( "hash", h, "peer_id", peer.PeerID).Errorf("Error updating peer: %s", err) } peers, err := s.getPeerHandout(d, h, peer) if err != nil { return nil, err } return &announceclient.Response{ Peers: peers, Interval: s.config.AnnounceInterval, }, nil } func (s *Server) getPeerHandout( d core.Digest, h core.InfoHash, peer *core.PeerInfo) ([]*core.PeerInfo, error) { if peer.Complete { // If the peer is announcing as complete, don't return a peer handout since // the peer does not need it. return nil, nil } var errs []error peers, err := s.peerStore.GetPeers(h, s.config.PeerHandoutLimit) if err != nil { errs = append(errs, fmt.Errorf("peer store: %s", err)) } origins, err := s.originStore.GetOrigins(d) if err != nil { errs = append(errs, fmt.Errorf("origin store: %s", err)) } peers = append(peers, origins...) if len(peers) == 0 { return nil, handler.Errorf("no peers available: %s", errutil.Join(errs)) } return s.policy.SortPeers(peer, peers), nil }