From 5965578c56678f6ac413fe02849f3ebaa116be2b Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Thu, 13 Apr 2017 11:55:14 +0400 Subject: [PATCH] [fuzz] only one way to set config variables --- fuzz.go | 157 +++++++++++++++++++++++++------------------------------- peer.go | 2 +- 2 files changed, 71 insertions(+), 88 deletions(-) diff --git a/fuzz.go b/fuzz.go index 822002b93..aefac986a 100644 --- a/fuzz.go +++ b/fuzz.go @@ -1,7 +1,6 @@ package p2p import ( - "fmt" "math/rand" "net" "sync" @@ -15,6 +14,19 @@ const ( FuzzModeDelay ) +// FuzzedConnection wraps any net.Conn and depending on the mode either delays +// reads/writes or randomly drops reads/writes/connections. +type FuzzedConnection struct { + conn net.Conn + + mtx sync.Mutex + start <-chan time.Time + active bool + + config *FuzzConnConfig +} + +// FuzzConnConfig is a FuzzedConnection configuration. type FuzzConnConfig struct { Mode int MaxDelay time.Duration @@ -23,7 +35,8 @@ type FuzzConnConfig struct { ProbSleep float64 } -func defaultFuzzConnConfig() *FuzzConnConfig { +// DefaultFuzzConnConfig returns the default config. +func DefaultFuzzConnConfig() *FuzzConnConfig { return &FuzzConnConfig{ Mode: FuzzModeDrop, MaxDelay: 3 * time.Second, @@ -33,86 +46,85 @@ func defaultFuzzConnConfig() *FuzzConnConfig { } } +// FuzzConn creates a new FuzzedConnection. Fuzzing starts immediately. func FuzzConn(conn net.Conn) net.Conn { - return FuzzConnFromConfig(conn, defaultFuzzConnConfig()) + return FuzzConnFromConfig(conn, DefaultFuzzConnConfig()) } +// FuzzConnFromConfig creates a new FuzzedConnection from a config. Fuzzing +// starts immediately. func FuzzConnFromConfig(conn net.Conn, config *FuzzConnConfig) net.Conn { return &FuzzedConnection{ - conn: conn, - start: make(<-chan time.Time), - active: true, - mode: config.Mode, - maxDelay: config.MaxDelay, - probDropRW: config.ProbDropRW, - probDropConn: config.ProbDropConn, - probSleep: config.ProbSleep, + conn: conn, + start: make(<-chan time.Time), + active: true, + config: config, } } +// FuzzConnAfter creates a new FuzzedConnection. Fuzzing starts when the +// duration elapses. func FuzzConnAfter(conn net.Conn, d time.Duration) net.Conn { - return FuzzConnAfterFromConfig(conn, d, defaultFuzzConnConfig()) + return FuzzConnAfterFromConfig(conn, d, DefaultFuzzConnConfig()) } +// FuzzConnAfterFromConfig creates a new FuzzedConnection from a config. +// Fuzzing starts when the duration elapses. func FuzzConnAfterFromConfig(conn net.Conn, d time.Duration, config *FuzzConnConfig) net.Conn { return &FuzzedConnection{ - conn: conn, - start: time.After(d), - active: false, - mode: config.Mode, - maxDelay: config.MaxDelay, - probDropRW: config.ProbDropRW, - probDropConn: config.ProbDropConn, - probSleep: config.ProbSleep, + conn: conn, + start: time.After(d), + active: false, + config: config, } } -// FuzzedConnection wraps any net.Conn and depending on the mode either delays -// reads/writes or randomly drops reads/writes/connections. -type FuzzedConnection struct { - conn net.Conn - - mtx sync.Mutex - start <-chan time.Time - active bool - - mode int - maxDelay time.Duration - probDropRW float64 - probDropConn float64 - probSleep float64 +// Config returns the connection's config. +func (fc *FuzzedConnection) Config() *FuzzConnConfig { + return fc.config } -func (fc *FuzzedConnection) randomDuration() time.Duration { - maxDelayMillis := int(fc.maxDelay.Nanoseconds() / 1000) - return time.Millisecond * time.Duration(rand.Int()%maxDelayMillis) +// Read implements net.Conn. +func (fc *FuzzedConnection) Read(data []byte) (n int, err error) { + if fc.fuzz() { + return 0, nil + } + return fc.conn.Read(data) } -func (fc *FuzzedConnection) SetMode(mode int) { - switch mode { - case FuzzModeDrop: - fc.mode = FuzzModeDrop - case FuzzModeDelay: - fc.mode = FuzzModeDelay - default: - panic(fmt.Sprintf("Unknown mode %d", mode)) +// Write implements net.Conn. +func (fc *FuzzedConnection) Write(data []byte) (n int, err error) { + if fc.fuzz() { + return 0, nil } + return fc.conn.Write(data) } -func (fc *FuzzedConnection) SetProbDropRW(prob float64) { - fc.probDropRW = prob -} +// Close implements net.Conn. +func (fc *FuzzedConnection) Close() error { return fc.conn.Close() } + +// LocalAddr implements net.Conn. +func (fc *FuzzedConnection) LocalAddr() net.Addr { return fc.conn.LocalAddr() } + +// RemoteAddr implements net.Conn. +func (fc *FuzzedConnection) RemoteAddr() net.Addr { return fc.conn.RemoteAddr() } + +// SetDeadline implements net.Conn. +func (fc *FuzzedConnection) SetDeadline(t time.Time) error { return fc.conn.SetDeadline(t) } -func (fc *FuzzedConnection) SetProbDropConn(prob float64) { - fc.probDropConn = prob +// SetReadDeadline implements net.Conn. +func (fc *FuzzedConnection) SetReadDeadline(t time.Time) error { + return fc.conn.SetReadDeadline(t) } -func (fc *FuzzedConnection) SetProbSleep(prob float64) { - fc.probSleep = prob +// SetWriteDeadline implements net.Conn. +func (fc *FuzzedConnection) SetWriteDeadline(t time.Time) error { + return fc.conn.SetWriteDeadline(t) } -func (fc *FuzzedConnection) SetMaxDelay(d time.Duration) { - fc.maxDelay = d +func (fc *FuzzedConnection) randomDuration() time.Duration { + maxDelayMillis := int(fc.config.MaxDelay.Nanoseconds() / 1000) + return time.Millisecond * time.Duration(rand.Int()%maxDelayMillis) } // implements the fuzz (delay, kill conn) @@ -122,18 +134,18 @@ func (fc *FuzzedConnection) fuzz() bool { return false } - switch fc.mode { + switch fc.config.Mode { case FuzzModeDrop: // randomly drop the r/w, drop the conn, or sleep r := rand.Float64() - if r <= fc.probDropRW { + if r <= fc.config.ProbDropRW { return true - } else if r < fc.probDropRW+fc.probDropConn { + } else if r < fc.config.ProbDropRW+fc.config.ProbDropConn { // XXX: can't this fail because machine precision? // XXX: do we need an error? fc.Close() return true - } else if r < fc.probDropRW+fc.probDropConn+fc.probSleep { + } else if r < fc.config.ProbDropRW+fc.config.ProbDropConn+fc.config.ProbSleep { time.Sleep(fc.randomDuration()) } case FuzzModeDelay: @@ -143,7 +155,6 @@ func (fc *FuzzedConnection) fuzz() bool { return false } -// we don't fuzz until start chan fires func (fc *FuzzedConnection) shouldFuzz() bool { if fc.active { return true @@ -160,31 +171,3 @@ func (fc *FuzzedConnection) shouldFuzz() bool { return false } } - -// Read implements net.Conn -func (fc *FuzzedConnection) Read(data []byte) (n int, err error) { - if fc.fuzz() { - return 0, nil - } - return fc.conn.Read(data) -} - -// Write implements net.Conn -func (fc *FuzzedConnection) Write(data []byte) (n int, err error) { - if fc.fuzz() { - return 0, nil - } - return fc.conn.Write(data) -} - -// Implements net.Conn -func (fc *FuzzedConnection) Close() error { return fc.conn.Close() } -func (fc *FuzzedConnection) LocalAddr() net.Addr { return fc.conn.LocalAddr() } -func (fc *FuzzedConnection) RemoteAddr() net.Addr { return fc.conn.RemoteAddr() } -func (fc *FuzzedConnection) SetDeadline(t time.Time) error { return fc.conn.SetDeadline(t) } -func (fc *FuzzedConnection) SetReadDeadline(t time.Time) error { - return fc.conn.SetReadDeadline(t) -} -func (fc *FuzzedConnection) SetWriteDeadline(t time.Time) error { - return fc.conn.SetWriteDeadline(t) -} diff --git a/peer.go b/peer.go index 6ef317378..3d2b4720d 100644 --- a/peer.go +++ b/peer.go @@ -52,7 +52,7 @@ func defaultPeerConfig() *PeerConfig { HandshakeTimeout: 20 * time.Second, DialTimeout: 3 * time.Second, MConfig: defaultMConnectionConfig(), - FuzzConfig: defaultFuzzConnConfig(), + FuzzConfig: DefaultFuzzConnConfig(), } }