Passed
Push — master ( 264314...6402cf )
by Patrick D
01:03
created

entropychecker.WaitForEntropy   C

Complexity

Conditions 10

Size

Total Lines 28
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 22
nop 0
dl 0
loc 28
rs 5.9999
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like entropychecker.WaitForEntropy often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package entropychecker
2
3
import (
4
	"errors"
5
	"io/ioutil"
6
	"runtime"
7
	"strconv"
8
	"strings"
9
	"time"
10
)
11
12
// MinimumEntropy is the minimum amount of entropy that will be considered safe.
13
// Set this to what you consider to be a 'safe' minimum entropy amount (in bits)
14
var MinimumEntropy = 128
15
16
// Timeout sets the maximum amount of time to wait for entropy.
17
// Waiting for entropy will time out after this amount of time. Setting to zero will never time out.
18
var Timeout = time.Second * 10
19
20
// The only supported OS is linux at this time.
21
var supportedOS = "linux"
22
23
// ErrTimeout is for when the system waits too long and gives up
24
var ErrTimeout = errors.New("entropychecker: Timed out waiting for sufficient entropy")
25
26
// ErrUnsupportedOS is for for an invalid OS that does not provide entropy estimates
27
var ErrUnsupportedOS = errors.New("entropychecker: Unsupported OS. Only Linux is supported")
28
29
// GetEntropy gets the entropy estimate. Returns the estimated entropy in bits
30
func GetEntropy() (int, error) {
31
	if runtime.GOOS != supportedOS {
32
		return 0, ErrUnsupportedOS
33
	}
34
35
	text, err := ioutil.ReadFile("/proc/sys/kernel/random/entropy_avail")
36
	if err != nil {
37
		return 0, err
38
	}
39
	return strconv.Atoi(strings.TrimSuffix(string(text), "\n"))
40
}
41
42
// WaitForEntropy blocks until sufficient entropy is available
43
func WaitForEntropy() error {
44
	if runtime.GOOS != supportedOS {
45
		return ErrUnsupportedOS
46
	}
47
48
	// set up the timeout
49
	timeout := make(chan bool, 1)
50
	if Timeout != 0 {
51
		go func(timeoutDuration time.Duration) {
52
			time.Sleep(timeoutDuration)
53
			timeout <- true
54
		}(Timeout)
55
	}
56
57
	for {
58
		entropy, err := GetEntropy()
59
60
		switch {
61
		case err != nil:
62
			return err
63
		case entropy > MinimumEntropy:
64
			return nil
65
		default:
66
			select {
67
			case <-timeout:
68
				return ErrTimeout
69
			default:
70
				time.Sleep(50 * time.Millisecond)
71
			}
72
		}
73
	}
74
}
75