summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Hawkins <[email protected]>2022-06-04 21:24:19 -0400
committerWill Hawkins <[email protected]>2022-06-04 21:24:19 -0400
commit9be87fa5ec89c9e393c9c93b3cb36668c71593d6 (patch)
tree7c5a5df400370660c670935dc36e2e4b0493ab86
parentde7a7bf994a020049eca89098aab9d13ff81f361 (diff)
[Feature] Add conditional compilation support for GetTCPInfo
Now there is functionality for conditionally supporting GetTCPInfo depending on the platform. If the platform supports it, then the client can call utilities.GetTCPInfo. In the case that the platform does not support the GetTCPInfo function call, the result is an error of the type `NotImplemented`.
-rw-r--r--lgc/lgc.go31
-rw-r--r--networkQuality.go7
-rw-r--r--utilities/tcpinfo_other.go18
-rw-r--r--utilities/tcpinfo_unix.go62
-rw-r--r--utilities/utilities.go54
5 files changed, 106 insertions, 66 deletions
diff --git a/lgc/lgc.go b/lgc/lgc.go
index 5b35fd1..fb51ec1 100644
--- a/lgc/lgc.go
+++ b/lgc/lgc.go
@@ -281,40 +281,40 @@ func (lgd *LoadGeneratingConnectionDownload) Start(
go lgd.doDownload(ctx)
return true
}
-func (lbd *LoadGeneratingConnectionDownload) IsValid() bool {
- return lbd.valid
+func (lgd *LoadGeneratingConnectionDownload) IsValid() bool {
+ return lgd.valid
}
-func (lbd *LoadGeneratingConnectionDownload) Stats() *stats.TraceStats {
- return &lbd.stats
+func (lgd *LoadGeneratingConnectionDownload) Stats() *stats.TraceStats {
+ return &lgd.stats
}
-func (lbd *LoadGeneratingConnectionDownload) doDownload(ctx context.Context) {
+func (lgd *LoadGeneratingConnectionDownload) doDownload(ctx context.Context) {
var request *http.Request = nil
var get *http.Response = nil
var err error = nil
if request, err = http.NewRequestWithContext(
- httptrace.WithClientTrace(ctx, lbd.tracer),
+ httptrace.WithClientTrace(ctx, lgd.tracer),
"GET",
- lbd.Path,
+ lgd.Path,
nil,
); err != nil {
- lbd.valid = false
+ lgd.valid = false
return
}
- lbd.downloadStartTime = time.Now()
- lbd.lastIntervalEnd = 0
+ lgd.downloadStartTime = time.Now()
+ lgd.lastIntervalEnd = 0
- if get, err = lbd.client.Do(request); err != nil {
- lbd.valid = false
+ if get, err = lgd.client.Do(request); err != nil {
+ lgd.valid = false
return
}
- cr := &countingReader{n: &lbd.downloaded, ctx: ctx, readable: get.Body}
+ cr := &countingReader{n: &lgd.downloaded, ctx: ctx, readable: get.Body}
_, _ = io.Copy(ioutil.Discard, cr)
get.Body.Close()
- if debug.IsDebug(lbd.debug) {
+ if debug.IsDebug(lgd.debug) {
fmt.Printf("Ending a load-generating download.\n")
}
}
@@ -426,6 +426,7 @@ func (lgu *LoadGeneratingConnectionUpload) Start(
return true
}
-func (lbd *LoadGeneratingConnectionUpload) Stats() *stats.TraceStats {
+func (lgu *LoadGeneratingConnectionUpload) Stats() *stats.TraceStats {
+ // Get all your stats from the download side of the LGC.
return nil
}
diff --git a/networkQuality.go b/networkQuality.go
index 7593714..d9bdc94 100644
--- a/networkQuality.go
+++ b/networkQuality.go
@@ -336,7 +336,12 @@ func main() {
fmt.Printf("OOPS: Could not get the TCP info for the connection (not a TCP connection)!\n")
}
if info, err := utilities.GetTCPInfo(tcpConn); err != nil {
- fmt.Printf("OOPS: Could not get the TCP info for the connection: %v!\n", err)
+ switch err.(type) {
+ case *utilities.NotImplemented:
+ fmt.Printf("GetTCPInfo not implemented on this platform.\n")
+ default:
+ fmt.Printf("OOPS: Could not get the TCP info for the connection: %v!\n", err)
+ }
} else {
utilities.PrintTCPInfo(info)
}
diff --git a/utilities/tcpinfo_other.go b/utilities/tcpinfo_other.go
new file mode 100644
index 0000000..8dd070b
--- /dev/null
+++ b/utilities/tcpinfo_other.go
@@ -0,0 +1,18 @@
+//go:build !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd
+// +build !darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd
+
+package utilities
+
+import (
+ "net"
+
+ "golang.org/x/sys/unix"
+)
+
+func GetTCPInfo(connection net.Conn) (*unix.TCPInfo, error) {
+ return nil, NotImplemented{Functionality: "GetTCPInfo"}
+}
+
+func PrintTCPInfo(info *unix.TCPInfo) {
+ return
+}
diff --git a/utilities/tcpinfo_unix.go b/utilities/tcpinfo_unix.go
new file mode 100644
index 0000000..b0b5252
--- /dev/null
+++ b/utilities/tcpinfo_unix.go
@@ -0,0 +1,62 @@
+//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd
+// +build darwin dragonfly freebsd linux netbsd openbsd
+
+package utilities
+
+import (
+ "fmt"
+ "net"
+
+ "golang.org/x/sys/unix"
+)
+
+func GetTCPInfo(connection net.Conn) (*unix.TCPInfo, error) {
+ tcpConn, ok := connection.(*net.TCPConn)
+ if !ok {
+ return nil, fmt.Errorf("connection is not a net.TCPConn")
+ }
+ rawConn, err := tcpConn.SyscallConn()
+ if err != nil {
+ return nil, err
+ }
+
+ var info *unix.TCPInfo = nil
+ rawConn.Control(func(fd uintptr) {
+ info, err = unix.GetsockoptTCPInfo(int(fd), unix.SOL_TCP, unix.TCP_INFO)
+ })
+ return info, err
+}
+
+func PrintTCPInfo(info *unix.TCPInfo) {
+ fmt.Printf("TCPInfo: \n")
+ fmt.Printf(" State: %v\n", info.State)
+ fmt.Printf(" Ca_state: %v\n", info.Ca_state)
+ fmt.Printf(" Retransmits: %v\n", info.Retransmits)
+ fmt.Printf(" Probes: %v\n", info.Probes)
+ fmt.Printf(" Backoff: %v\n", info.Backoff)
+ fmt.Printf(" Options: %v\n", info.Options)
+ fmt.Printf(" Rto: %v\n", info.Rto)
+ fmt.Printf(" Ato: %v\n", info.Ato)
+ fmt.Printf(" Snd_mss: %v\n", info.Snd_mss)
+ fmt.Printf(" Rcv_mss: %v\n", info.Rcv_mss)
+ fmt.Printf(" Unacked: %v\n", info.Unacked)
+ fmt.Printf(" Sacked: %v\n", info.Sacked)
+ fmt.Printf(" Lost: %v\n", info.Lost)
+ fmt.Printf(" Retrans: %v\n", info.Retrans)
+ fmt.Printf(" Fackets: %v\n", info.Fackets)
+ fmt.Printf(" Last_data_sent: %v\n", info.Last_data_sent)
+ fmt.Printf(" Last_ack_sent: %v\n", info.Last_ack_sent)
+ fmt.Printf(" Last_data_recv: %v\n", info.Last_data_recv)
+ fmt.Printf(" Last_ack_recv: %v\n", info.Last_ack_recv)
+ fmt.Printf(" Pmtu: %v\n", info.Pmtu)
+ fmt.Printf(" Rcv_ssthresh: %v\n", info.Rcv_ssthresh)
+ fmt.Printf(" Rtt: %v\n", info.Rtt)
+ fmt.Printf(" Rttvar: %v\n", info.Rttvar)
+ fmt.Printf(" Snd_ssthresh: %v\n", info.Snd_ssthresh)
+ fmt.Printf(" Snd_cwnd: %v\n", info.Snd_cwnd)
+ fmt.Printf(" Advmss: %v\n", info.Advmss)
+ fmt.Printf(" Reordering: %v\n", info.Reordering)
+ fmt.Printf(" Rcv_rtt: %v\n", info.Rcv_rtt)
+ fmt.Printf(" Rcv_space: %v\n", info.Rcv_space)
+ fmt.Printf(" Total_retrans: %v\n", info.Total_retrans)
+}
diff --git a/utilities/utilities.go b/utilities/utilities.go
index e4c8a0d..7e26ab9 100644
--- a/utilities/utilities.go
+++ b/utilities/utilities.go
@@ -18,13 +18,10 @@ import (
"fmt"
"math"
"math/rand"
- "net"
"os"
"reflect"
"sync/atomic"
"time"
-
- "golang.org/x/sys/unix"
)
func IsInterfaceNil(ifc interface{}) bool {
@@ -126,53 +123,10 @@ func RandBetween(max int) int {
return rand.New(rand.NewSource(int64(time.Now().Nanosecond()))).Int() % max
}
-func GetTCPInfo(connection net.Conn) (*unix.TCPInfo, error) {
- tcpConn, ok := connection.(*net.TCPConn)
- if !ok {
- return nil, fmt.Errorf("connection is not a net.TCPConn")
- }
- rawConn, err := tcpConn.SyscallConn()
- if err != nil {
- return nil, err
- }
-
- var info *unix.TCPInfo = nil
- rawConn.Control(func(fd uintptr) {
- info, err = unix.GetsockoptTCPInfo(int(fd), unix.SOL_TCP, unix.TCP_INFO)
- })
- return info, err
+type NotImplemented struct {
+ Functionality string
}
-func PrintTCPInfo(info *unix.TCPInfo) {
- fmt.Printf("TCPInfo: \n")
- fmt.Printf(" State: %v\n", info.State)
- fmt.Printf(" Ca_state: %v\n", info.Ca_state)
- fmt.Printf(" Retransmits: %v\n", info.Retransmits)
- fmt.Printf(" Probes: %v\n", info.Probes)
- fmt.Printf(" Backoff: %v\n", info.Backoff)
- fmt.Printf(" Options: %v\n", info.Options)
- fmt.Printf(" Rto: %v\n", info.Rto)
- fmt.Printf(" Ato: %v\n", info.Ato)
- fmt.Printf(" Snd_mss: %v\n", info.Snd_mss)
- fmt.Printf(" Rcv_mss: %v\n", info.Rcv_mss)
- fmt.Printf(" Unacked: %v\n", info.Unacked)
- fmt.Printf(" Sacked: %v\n", info.Sacked)
- fmt.Printf(" Lost: %v\n", info.Lost)
- fmt.Printf(" Retrans: %v\n", info.Retrans)
- fmt.Printf(" Fackets: %v\n", info.Fackets)
- fmt.Printf(" Last_data_sent: %v\n", info.Last_data_sent)
- fmt.Printf(" Last_ack_sent: %v\n", info.Last_ack_sent)
- fmt.Printf(" Last_data_recv: %v\n", info.Last_data_recv)
- fmt.Printf(" Last_ack_recv: %v\n", info.Last_ack_recv)
- fmt.Printf(" Pmtu: %v\n", info.Pmtu)
- fmt.Printf(" Rcv_ssthresh: %v\n", info.Rcv_ssthresh)
- fmt.Printf(" Rtt: %v\n", info.Rtt)
- fmt.Printf(" Rttvar: %v\n", info.Rttvar)
- fmt.Printf(" Snd_ssthresh: %v\n", info.Snd_ssthresh)
- fmt.Printf(" Snd_cwnd: %v\n", info.Snd_cwnd)
- fmt.Printf(" Advmss: %v\n", info.Advmss)
- fmt.Printf(" Reordering: %v\n", info.Reordering)
- fmt.Printf(" Rcv_rtt: %v\n", info.Rcv_rtt)
- fmt.Printf(" Rcv_space: %v\n", info.Rcv_space)
- fmt.Printf(" Total_retrans: %v\n", info.Total_retrans)
+func (ni *NotImplemented) Error() string {
+ return fmt.Sprintf("%v not implemented.\n", ni.Functionality)
}