-
Notifications
You must be signed in to change notification settings - Fork 7
Refactor main networking code #8
Conversation
Refactor code to improve readability and modular
… and filter in one func
@NullHypothesis marking this ready to get preliminary feedback on how I'm going about with the refactoring. Let me know if this is a good start. |
Unrelated to the actual code: Take a look at the commit guidelines of the Pro Git book. You're doing pretty well on that front already but the section contains a few helpful suggestions, like limiting the first line of a commit message to <=50 characters. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a bunch of comments. I hope it's helpful!
cmd/test-server/handlers.go
Outdated
clientIP, clPort, _ := net.SplitHostPort(clientIPstr) | ||
clientPort, _ := strconv.Atoi(clPort) | ||
|
||
zeroTraceInstance := newZeroTrace(deviceName, myConn, uuid, clientIP, clientPort) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would only pass myConn
to newZeroTrace
. The function can then extract IP addresses and ports from the connection. No need to pass them separately.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 7dd7051
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a big improvement in clarity. Nice!
cmd/test-server/util.go
Outdated
@@ -16,3 +21,61 @@ func isValidUUID(u string) bool { | |||
func fmtTimeMs(value time.Duration) float64 { | |||
return (float64(value) / float64(time.Millisecond)) | |||
} | |||
|
|||
// getMeanIcmpRTT gets Avg RTT from all successful ICMP measurements, to display on webpage | |||
func getMeanIcmpRTT(icmp []RtItem) float64 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is RtItem
short for? Round Trip Item? I've always been a bit confused by the name. Some suggestions for a better name:
- RttResult
- RttMsmt
- HopResult
- HopMsmt
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 7dd7051
cmd/test-server/zerotrace.go
Outdated
|
||
const ( | ||
beginTTLValue = 5 | ||
MaxTTLHops = 32 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent capitalization of constants. I generally suggest lowercase unless you want to export a constant for use outside of this package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 7dd7051
cmd/test-server/zerotrace.go
Outdated
) | ||
|
||
var ( | ||
buffer gopacket.SerializeBuffer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of these variables are only used once and don't need to be global. In that case, I suggest inlining them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
icmpPktError = errors.New("IP header unavailable") | ||
) | ||
|
||
type SentPacketData struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a doc string explaining what this is used for? It's not immediately clear from the name only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added in 0e14997
cmd/test-server/zerotrace.go
Outdated
} | ||
|
||
// recvPackets listens on the provided pcap handler for packets sent, processes TCP and ICMP packets differently | ||
func (z *zeroTrace) recvPackets(pcapHdl *pcap.Handle, hops chan HopRTT) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible that this function won't return if we never get the ICMP packets that we're expecting? It should probably take as input some sort of abort signal from the caller, instructing the function to return when the caller is done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right. I'll add an abort signal that makes this function return when the tracerouteHopTimeout is reached (and yet no ICMP packets are received) for the last probe. Added in c08b5db.
cmd/test-server/zerotrace.go
Outdated
return nil, err | ||
} | ||
if err = pcapHdl.SetBPFFilter(fmt.Sprintf("(tcp and port %d and host %s) or icmp", z.ClientPort, z.ClientIP)); err != nil { | ||
ErrLogger.Fatal(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not exit the program here, and simply propagate the error. It should be up to the code that's using zeroTrace to decide what to do with that error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in b5c2e3d
cmd/test-server/zerotrace.go
Outdated
// Create the packet with the layers | ||
buffer = gopacket.NewSerializeBuffer() | ||
|
||
serializeErr := gopacket.SerializeLayers(buffer, options, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: I'd simply call each error err. That's both idiomatic and reduces the cognitive load of reviewers because if every error is called err, there are fewer variables to keep track of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in ffe573f
cmd/test-server/zerotrace.go
Outdated
gopacket.Payload(rawBytes), | ||
) | ||
if serializeErr != nil { | ||
ErrLogger.Println("Send Packet Error: Serialize: ", serializeErr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could save ourselves all these log messages if the caller checks if sendTracePacket
returned and error, and if so, we can do something like:
if err := z.sendTracePacket(ttlValue); err != nil {
ErrLogger.Println("Send Packet Error: ", err)
return traceroute, sendError
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, and done in ffe573f
cmd/test-server/zerotrace.go
Outdated
PcapHdl *pcap.Handle | ||
ClientIP string | ||
ClientPort int | ||
IPIdHop map[int][]SentPacketData |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we anticipating concurrent reads/writes to this map?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(I've renamed this map to SentPktsIPId
in 0e14997)
It is a map of the IPIds and sent times of the sent packets for each TTL. I don't expect concurrent reads or writes because each packet---sent packet (writes to this) or received packet (reads from this)---is dealt with sequentially.
Fix inconsistent capitalization, inline variables, don't pass variables that can be derived
Remove excessive logging and log at caller, avoid special err variables
Add a html form to have users submit contact info to help debug
select { | ||
case <-quit: | ||
return |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've found an issue with this:
In this file L:113, we feed "true" to the quit channel once the sendTTLIncrementingProbes
function returns. But since I am working with the packet stream here, I need to wait until another packet is seen on this handle before being able to quit. Moving the select statement out also does not work since the execution will be stuck in the for packet := range packetStream.Packets()
loop.
Trying to fix this now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A fix has been pushed in a89c1d2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the same fix that I had in mind when reviewing the code 👍
Fix issue by reading from packet stream as a channel, do not check for isClientReached? in recvPackets, instead let sender figure it out and abort the receive goroutine
Thanks for addressing all the feedback and for doing it in separate commits. That makes it much easier for me to see what changed. Let's not have the perfect be the enemy of the good, and merge this. We can still improve the code and add tests in follow-up PRs. |
Input form to collect user details
Merged PR#9 into this and then this PR into main. Thanks for your comments! 🚀 |
Refactor code to improve readability and modularity
For now,
This is still a
work in progress