}
portU64, err := strconv.ParseUint(vs.Get("port"), 0, 16)
addrPort := netip.AddrPortFrom(addr, uint16(portU64))
- peers, err := me.Announce.Serve(r.Context(), tracker.AnnounceRequest{
+ res := me.Announce.Serve(r.Context(), tracker.AnnounceRequest{
InfoHash: infoHash,
PeerId: peerId,
Event: event,
Port: addrPort.Port(),
NumWant: -1,
- }, addrPort, tracker.GetPeersOpts{generics.Some[uint](200)})
+ }, addrPort, tracker.GetPeersOpts{MaxCount: generics.Some[uint](200)})
+ err = res.Err
if err != nil {
log.Printf("error serving announce: %v", err)
http.Error(w, "error handling announce", http.StatusInternalServerError)
return
}
var resp httpTracker.HttpResponse
- resp.Interval = 5 * 60
+ resp.Interval = res.Interval.UnwrapOr(5 * 60)
resp.Peers.Compact = true
- for _, peer := range peers {
+ for _, peer := range res.Peers {
if peer.Addr().Is4() {
resp.Peers.List = append(resp.Peers.List, tracker.Peer{
IP: peer.Addr().AsSlice(),
type AnnounceTracker interface {
TrackAnnounce(ctx context.Context, req udp.AnnounceRequest, addr AnnounceAddr) error
Scrape(ctx context.Context, infoHashes []InfoHash) ([]udp.ScrapeInfohashResult, error)
- GetPeers(ctx context.Context, infoHash InfoHash, opts GetPeersOpts) ([]PeerInfo, error)
+ GetPeers(ctx context.Context, infoHash InfoHash, opts GetPeersOpts) ServerAnnounceResult
+}
+
+type ServerAnnounceResult struct {
+ Err error
+ Peers []PeerInfo
+ Interval generics.Option[int32]
+ Leechers generics.Option[int32]
+ Seeders generics.Option[int32]
}
type AnnounceHandler struct {
func (me *AnnounceHandler) Serve(
ctx context.Context, req AnnounceRequest, addr AnnounceAddr, opts GetPeersOpts,
-) (peers []PeerInfo, err error) {
+) (ret ServerAnnounceResult) {
ctx, span := tracer.Start(
ctx,
"AnnounceHandler.Serve",
)
defer span.End()
defer func() {
- span.SetAttributes(attribute.Int("announce.get_peers.len", len(peers)))
+ span.SetAttributes(attribute.Int("announce.get_peers.len", len(ret.Peers)))
}()
- err = me.AnnounceTracker.TrackAnnounce(ctx, req, addr)
- if err != nil {
+ ret.Err = me.AnnounceTracker.TrackAnnounce(ctx, req, addr)
+ if ret.Err != nil {
return
}
infoHash := req.InfoHash
opts.MaxCount = generics.Some(newCount)
}
}
- peers, err = me.AnnounceTracker.GetPeers(ctx, infoHash, opts)
- if err != nil {
+ ret = me.AnnounceTracker.GetPeers(ctx, infoHash, opts)
+ if ret.Err != nil {
return
}
// Take whatever peers it has ready. If it's finished, it doesn't matter if we do this inside
// the mutex or not.
if op.Ok {
curPeers, done := op.Value.getCurPeersAndDone()
- addMissing(peers, curPeers)
+ addMissing(ret.Peers, curPeers)
if done {
// It doesn't get any better with this operation. Forget it.
op.Ok = false
// assuming the announcing peer might be that one. Really we should record a value to prevent
// duplicate announces. Also don't announce upstream if we got no peers because the caller asked
// for none.
- if !op.Ok && len(peers) <= 1 && opts.MaxCount.UnwrapOr(1) > 0 {
+ if !op.Ok && len(ret.Peers) <= 1 && opts.MaxCount.UnwrapOr(1) > 0 {
op.Value, op.Ok = me.ongoingUpstreamAugmentations[infoHash]
if !op.Ok {
op.Set(me.augmentPeersFromUpstream(req.InfoHash))
case <-op.Value.doneAnnouncing:
}
cancel()
- addMissing(peers, op.Value.getCurPeers())
+ addMissing(ret.Peers, op.Value.getCurPeers())
}
return
}
if addrFamily == udp.AddrFamilyIpv4 {
opts.MaxCount = generics.Some[uint](150)
}
- peers, err := me.Announce.Serve(ctx, req, announceAddr, opts)
- if err != nil {
- return err
+ res := me.Announce.Serve(ctx, req, announceAddr, opts)
+ if res.Err != nil {
+ return res.Err
}
- nodeAddrs := make([]krpc.NodeAddr, 0, len(peers))
- for _, p := range peers {
+ nodeAddrs := make([]krpc.NodeAddr, 0, len(res.Peers))
+ for _, p := range res.Peers {
var ip net.IP
switch addrFamily {
default:
if err != nil {
return err
}
- err = udp.Write(&buf, udp.AnnounceResponseHeader{})
+ err = udp.Write(&buf, udp.AnnounceResponseHeader{
+ Interval: res.Interval.UnwrapOr(5 * 60),
+ })
if err != nil {
return err
}