New returns an unstarted Engine bound to a backend.
(cfg Config, be platform.Backend)
| 58 | |
| 59 | // New returns an unstarted Engine bound to a backend. |
| 60 | func New(cfg Config, be platform.Backend) (*Engine, error) { |
| 61 | if len(cfg.SNIPool) == 0 { |
| 62 | return nil, errors.New("engine: SNIPool must be non-empty") |
| 63 | } |
| 64 | // Validate the fallback and any rotation entries up front so we fail fast. |
| 65 | if _, err := bypass.ByName(cfg.Strategy); err != nil { |
| 66 | return nil, err |
| 67 | } |
| 68 | for _, n := range cfg.Knobs.StrategyRotation { |
| 69 | if _, err := bypass.ByName(n); err != nil { |
| 70 | return nil, fmt.Errorf("engine: invalid strategy_rotation entry: %w", err) |
| 71 | } |
| 72 | } |
| 73 | if cfg.InjectDelay <= 0 { |
| 74 | cfg.InjectDelay = 1 * time.Millisecond |
| 75 | } |
| 76 | // If caller didn't set timing knob min/max, fold the static InjectDelay in. |
| 77 | if !cfg.Knobs.RandomizeTiming { |
| 78 | cfg.Knobs.MinDelay = cfg.InjectDelay |
| 79 | cfg.Knobs.MaxDelay = cfg.InjectDelay |
| 80 | } |
| 81 | return &Engine{ |
| 82 | cfg: cfg, |
| 83 | backend: be, |
| 84 | rnd: fingerprint.New(cfg.Knobs), |
| 85 | table: conntrack.NewTable(), |
| 86 | }, nil |
| 87 | } |
| 88 | |
| 89 | // Run consumes the backend's packet stream until ctx is done. |
| 90 | func (e *Engine) Run(ctx context.Context) error { |