drainer.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. package drain
  2. import (
  3. "io"
  4. "github.com/xtls/xray-core/common/dice"
  5. "github.com/xtls/xray-core/common/errors"
  6. )
  7. type BehaviorSeedLimitedDrainer struct {
  8. DrainSize int
  9. }
  10. func NewBehaviorSeedLimitedDrainer(behaviorSeed int64, drainFoundation, maxBaseDrainSize, maxRandDrain int) (Drainer, error) {
  11. behaviorRand := dice.NewDeterministicDice(behaviorSeed)
  12. BaseDrainSize := behaviorRand.Roll(maxBaseDrainSize)
  13. RandDrainMax := behaviorRand.Roll(maxRandDrain) + 1
  14. RandDrainRolled := dice.Roll(RandDrainMax)
  15. DrainSize := drainFoundation + BaseDrainSize + RandDrainRolled
  16. return &BehaviorSeedLimitedDrainer{DrainSize: DrainSize}, nil
  17. }
  18. func (d *BehaviorSeedLimitedDrainer) AcknowledgeReceive(size int) {
  19. d.DrainSize -= size
  20. }
  21. func (d *BehaviorSeedLimitedDrainer) Drain(reader io.Reader) error {
  22. if d.DrainSize > 0 {
  23. err := drainReadN(reader, d.DrainSize)
  24. if err == nil {
  25. return errors.New("drained connection")
  26. }
  27. return errors.New("unable to drain connection").Base(err)
  28. }
  29. return nil
  30. }
  31. func drainReadN(reader io.Reader, n int) error {
  32. _, err := io.CopyN(io.Discard, reader, int64(n))
  33. return err
  34. }
  35. func WithError(drainer Drainer, reader io.Reader, err error) error {
  36. drainErr := drainer.Drain(reader)
  37. if drainErr == nil {
  38. return err
  39. }
  40. return errors.New(drainErr).Base(err)
  41. }
  42. type NopDrainer struct{}
  43. func (n NopDrainer) AcknowledgeReceive(size int) {
  44. }
  45. func (n NopDrainer) Drain(reader io.Reader) error {
  46. return nil
  47. }
  48. func NewNopDrainer() Drainer {
  49. return &NopDrainer{}
  50. }