smartban.go 1.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. package torrent
  2. import (
  3. "bytes"
  4. "net/netip"
  5. g "github.com/anacrolix/generics"
  6. "github.com/anacrolix/torrent/smartban"
  7. )
  8. type bannableAddr = netip.Addr
  9. type smartBanCache = smartban.Cache[bannableAddr, RequestIndex, uint64]
  10. type blockCheckingWriter struct {
  11. cache *smartBanCache
  12. requestIndex RequestIndex
  13. // Peers that didn't match blocks written now.
  14. badPeers map[bannableAddr]struct{}
  15. blockBuffer bytes.Buffer
  16. chunkSize int
  17. }
  18. func (me *blockCheckingWriter) checkBlock() {
  19. b := me.blockBuffer.Next(me.chunkSize)
  20. for _, peer := range me.cache.CheckBlock(me.requestIndex, b) {
  21. g.MakeMapIfNilAndSet(&me.badPeers, peer, struct{}{})
  22. }
  23. me.requestIndex++
  24. }
  25. func (me *blockCheckingWriter) checkFullBlocks() {
  26. for me.blockBuffer.Len() >= me.chunkSize {
  27. me.checkBlock()
  28. }
  29. }
  30. func (me *blockCheckingWriter) Write(b []byte) (int, error) {
  31. n, err := me.blockBuffer.Write(b)
  32. if err != nil {
  33. // bytes.Buffer.Write should never fail.
  34. panic(err)
  35. }
  36. me.checkFullBlocks()
  37. return n, err
  38. }
  39. // Check any remaining block data. Terminal pieces or piece sizes that don't divide into the chunk
  40. // size cleanly may leave fragments that should be checked.
  41. func (me *blockCheckingWriter) Flush() {
  42. for me.blockBuffer.Len() != 0 {
  43. me.checkBlock()
  44. }
  45. }