TUN-8762: fix argument order when invoking tracert and modify network info output parsing.

## Summary

The windows code path has three bugs:

* the -4 and -6 option cannot be passed in the last position
* since there are some lines in the command output that are not parsable the collection fails to parse any kind of output
* the timeout hop is not correctly parsed

This PR also guards the parsing code against empty domains

Closes TUN-8762
This commit is contained in:
Luis Neto
2024-12-03 04:56:28 -08:00
parent 65786597cc
commit 1ef109c042
6 changed files with 186 additions and 47 deletions

View File

@@ -14,7 +14,13 @@ import (
type NetworkCollectorImpl struct{}
func (tracer *NetworkCollectorImpl) Collect(ctx context.Context, options TraceOptions) ([]*Hop, string, error) {
ipversion := "-4"
if !options.useV4 {
ipversion = "-6"
}
args := []string{
ipversion,
"-w",
strconv.FormatInt(int64(options.timeout.Seconds()), 10),
"-h",
@@ -23,17 +29,14 @@ func (tracer *NetworkCollectorImpl) Collect(ctx context.Context, options TraceOp
"-d",
options.address,
}
if options.useV4 {
args = append(args, "-4")
} else {
args = append(args, "-6")
}
command := exec.CommandContext(ctx, "tracert.exe", args...)
return decodeNetworkOutputToFile(command, DecodeLine)
}
func DecodeLine(text string) (*Hop, error) {
const requestTimedOut = "Request timed out."
fields := strings.Fields(text)
parts := []string{}
filter := func(s string) bool { return s != "*" && s != "ms" }
@@ -49,10 +52,6 @@ func DecodeLine(text string) (*Hop, error) {
return nil, fmt.Errorf("couldn't parse index from timeout hop: %w", err)
}
if len(parts) == 1 {
return NewTimeoutHop(uint8(index)), nil
}
domain := ""
rtts := []time.Duration{}
@@ -66,6 +65,17 @@ func DecodeLine(text string) (*Hop, error) {
rtts = append(rtts, time.Duration(rtt*MicrosecondsFactor))
}
}
domain, _ = strings.CutSuffix(domain, " ")
// If the domain is equal to "Request timed out." then we build a
// timeout hop.
if domain == requestTimedOut {
return NewTimeoutHop(uint8(index)), nil
}
if domain == "" {
return nil, ErrEmptyDomain
}
return NewHop(uint8(index), domain, rtts), nil
}