Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,21 @@ import (
"netexp/netdev"
"netexp/pipeline"
"os"
"sync"
"time"
)

var (
version = "0.3.8"
metrics []byte
listen string
getver bool
)

var (
mu sync.RWMutex // guards the metrics
metrics []byte
)

func main() {
// get options from flags
flag.StringVar(&listen, "listen", ":9298", "network address to listen on")
Expand Down Expand Up @@ -45,6 +50,8 @@ func serve() {
})

http.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) {
mu.RLock()
defer mu.RUnlock()
w.Write(metrics)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This opens up the possibility for DoS. w.Write() could potentially take a long time to finish, during which time the gather goroutine would be locked. At best, the now incorrect timings of the p.Step() calls would result in incorrect metrics. At worst, a rogue, slow connection could take down the entire server.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, if the problem is with the HTTP I/O operation duration, can't we just make a copy of the latest matrics variable? This way, the mu.Unlock() doesn't at the HTTP I/O Duration mecry.
Here:

	http.HandleFunc("/metrics", func(w http.ResponseWriter, r *http.Request) {
		mu.RLock()
		metricsCopy := make([]byte, len(metrics))
		_ = copy(metricsCopy, metrics)
		mu.RUnlock()

		w.Write(metricsCopy)
	})

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would create a copy of metrics for every HTTP connection, using up memory, which again would allow a potential DoS with lots of connections.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About the http server in general, the program can benefit from having a deadline for both Read and Write Operations.

})

Expand Down Expand Up @@ -72,7 +79,9 @@ func gather() {
panic(fmt.Errorf("could not get traffic: %w", err))
}

mu.Lock()
metrics = p.Step(recv, trns)
mu.Unlock()

time.Sleep(time.Second)
}
Expand Down
Loading