initial implementation

main
Ben Grewell 4 years ago
parent 03148c6413
commit a7116fd4a1

@ -2,15 +2,16 @@
<project version="4">
<component name="ChangeListManager">
<list default="true" id="fc2840de-29dc-4fca-8e0e-a283562f60ca" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/bindata.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/cmd/main.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/go.mod" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.gitignore" beforeDir="false" afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/go-iperf.iml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/go-iperf.iml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/client.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/execute.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/protocol.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/server.go" afterDir="false" />
<change afterPath="$PROJECT_DIR$/shared.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/embedded/cygwin1.dll" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/embedded/iperf3" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/embedded/iperf3.exe" beforeDir="false" />
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
<change beforePath="$PROJECT_DIR$/bindata.go" beforeDir="false" afterPath="$PROJECT_DIR$/bindata.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/cmd/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/main.go" afterDir="false" />
<change beforePath="$PROJECT_DIR$/go.mod" beforeDir="false" afterPath="$PROJECT_DIR$/go.mod" afterDir="false" />
<change beforePath="$PROJECT_DIR$/iperf.go" beforeDir="false" afterPath="$PROJECT_DIR$/iperf.go" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
@ -21,8 +22,8 @@
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Go File" />
<option value="Go Application" />
<option value="Go File" />
</list>
</option>
</component>
@ -30,17 +31,21 @@
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="GoLibraries">
<option name="indexEntireGoPath" value="false" />
</component>
<component name="ProjectId" id="1lhjlU9mkZIWjchkp4HkX1szrI1" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="DefaultGoTemplateProperty" value="Go Application" />
<property name="DefaultGoTemplateProperty" value="Go File" />
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="go.import.settings.migrated" value="true" />
<property name="go.sdk.automatically.set" value="true" />
<property name="go.tried.to.enable.integration.vgo.integrator" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/embedded" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
@ -50,8 +55,53 @@
<recent name="C:\Users\BGrewell\repos\go-iperf\embedded" />
</key>
</component>
<component name="RunManager">
<configuration name="go build github.com/BGrewell/go-iperf/cmd" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true" nameIsGenerated="true">
<module name="go-iperf" />
<working_directory value="$PROJECT_DIR$" />
<kind value="PACKAGE" />
<filePath value="$PROJECT_DIR$/cmd/main.go" />
<package value="github.com/BGrewell/go-iperf/cmd" />
<directory value="$PROJECT_DIR$" />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="Go Build.go build github.com/BGrewell/go-iperf/cmd" />
</list>
</recent_temporary>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="VgoProject">
<integration-enabled>true</integration-enabled>
</component>
<component name="WindowStateProjectService">
<state x="652" y="533" key="#Go_Modules" timestamp="1608060904277">
<screen x="0" y="0" width="3440" height="1400" />
</state>
<state x="652" y="533" key="#Go_Modules/0.0.3440.1400@0.0.3440.1400" timestamp="1608060904277" />
<state width="1676" height="403" key="GridCell.Tab.0.bottom" timestamp="1608066744405">
<screen x="0" y="0" width="3440" height="1400" />
</state>
<state width="1676" height="403" key="GridCell.Tab.0.bottom/0.0.3440.1400@0.0.3440.1400" timestamp="1608066744405" />
<state width="1676" height="403" key="GridCell.Tab.0.center" timestamp="1608066744404">
<screen x="0" y="0" width="3440" height="1400" />
</state>
<state width="1676" height="403" key="GridCell.Tab.0.center/0.0.3440.1400@0.0.3440.1400" timestamp="1608066744404" />
<state width="1676" height="403" key="GridCell.Tab.0.left" timestamp="1608066744404">
<screen x="0" y="0" width="3440" height="1400" />
</state>
<state width="1676" height="403" key="GridCell.Tab.0.left/0.0.3440.1400@0.0.3440.1400" timestamp="1608066744404" />
<state width="1676" height="403" key="GridCell.Tab.0.right" timestamp="1608066744404">
<screen x="0" y="0" width="3440" height="1400" />
</state>
<state width="1676" height="403" key="GridCell.Tab.0.right/0.0.3440.1400@0.0.3440.1400" timestamp="1608066744404" />
<state x="431" y="297" key="com.intellij.openapi.editor.actions.MultiplePasteAction$ClipboardContentChooser" timestamp="1608062415393">
<screen x="0" y="0" width="3440" height="1400" />
</state>
<state x="431" y="297" key="com.intellij.openapi.editor.actions.MultiplePasteAction$ClipboardContentChooser/0.0.3440.1400@0.0.3440.1400" timestamp="1608062415393" />
</component>
</project>

@ -1,2 +1,6 @@
# go-iperf
A Go based wrapper around iperf3
```
go-bindata -pkg iperf -prefix "embedded/" embedded/```

File diff suppressed because one or more lines are too long

@ -0,0 +1,43 @@
package iperf
import "github.com/google/uuid"
func NewClient() *Client {
json := true
proto := Protocol(PROTO_TCP)
time := 10
length := "128KB"
streams := 1
c := &Client{
JSON: &json,
Proto: &proto,
TimeSec: &time,
Length: &length,
Streams: &streams,
}
c.Id = uuid.New().String()
return c
}
type Client struct {
SharedOptions
Host string
Proto *Protocol
Bandwidth *string
TimeSec *int
Bytes *string
BlockCount *string
Length *string
Streams *int
Reverse *bool
Window *string
MSS *int
NoDelay *bool
Version4 *bool
Version6 *bool
TOS *int
ZeroCopy *bool
OmitSec *int
Prefix *string
JSON *bool
}

@ -1,5 +1,25 @@
package main
import (
"fmt"
"github.com/BGrewell/go-iperf"
"time"
)
func main() {
s := iperf.NewServer()
c := iperf.NewClient()
fmt.Println(s.Id)
fmt.Println(c.Id)
err := s.Start()
if err != nil {
fmt.Println(err)
}
for s.Running {
time.Sleep(1 * time.Second)
}
fmt.Printf("Server exit code: %d\n", *s.ExitCode)
iperf.Cleanup()
}

@ -0,0 +1,41 @@
package iperf
import (
"io"
"os/exec"
"strings"
"syscall"
)
func Execute(cmd string, outPipe io.ReadCloser, errPipe io.ReadCloser, exit chan <- int) (err error) {
cmdParts := strings.Fields(cmd)
binary, err := exec.LookPath(cmdParts[0])
if err != nil {
return err
}
exe := exec.Command(binary, cmdParts[1:]...)
outPipe, err = exe.StdoutPipe()
if err != nil {
return err
}
errPipe, err = exe.StderrPipe()
if err != nil {
return err
}
err = exe.Start()
if err != nil {
return err
}
go func() {
if err := exe.Wait(); err != nil {
if exiterr, ok := err.(*exec.ExitError); ok {
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
exit <- status.ExitStatus()
}
}
} else {
exit <- 0
}
}()
return nil
}

@ -1,3 +1,5 @@
module github.com/BGrewell/go-iperf
go 1.15
require github.com/google/uuid v1.1.2

@ -0,0 +1,2 @@
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

@ -1,2 +1,70 @@
package iperf
import (
"fmt"
"io/ioutil"
"log"
"os"
"path"
"runtime"
)
var (
Debug = true
binaryDir = ""
binaryLocation = ""
)
func init() {
// Extract the binaries
if runtime.GOOS == "windows" {
err := extractWindowsEmbeddedBinaries()
if err != nil {
log.Fatalf("error initializing iperf: %v", err)
}
} else {
err := extractLinuxEmbeddedBinaries()
if err != nil {
log.Fatalf("error initializing iperf: %v", err)
}
}
}
func Cleanup() {
os.RemoveAll(binaryDir)
}
func extractWindowsEmbeddedBinaries() (err error) {
files := []string{"cygwin1.dll", "iperf3.exe"}
err = extractEmbeddedBinaries(files)
binaryLocation = path.Join(binaryDir, "iperf3.exe")
return err
}
func extractLinuxEmbeddedBinaries() (err error) {
files := []string{"iperf3"}
err = extractEmbeddedBinaries(files)
binaryLocation = path.Join(binaryDir, "iperf3")
return err
}
func extractEmbeddedBinaries(files []string) (err error) {
binaryDir, err = ioutil.TempDir("", "goiperf")
if err != nil {
return fmt.Errorf("failed to create temporary iperf directory: %v", err)
}
for _, file := range files {
data, err := Asset(file)
if err != nil {
return fmt.Errorf("failed to extract embedded iperf: %v", err)
}
err = ioutil.WriteFile(path.Join(binaryDir, file), data, 0755)
if err != nil {
return fmt.Errorf("failed to save embedded iperf: %v", err)
}
if Debug {
log.Printf("extracted file: %s\n", path.Join(binaryDir, file))
}
}
return nil
}

@ -0,0 +1,8 @@
package iperf
type Protocol string
const (
PROTO_TCP = "tcp"
PROTO_UDP = "udp"
)

@ -0,0 +1,50 @@
package iperf
import (
"fmt"
"github.com/google/uuid"
"io"
)
func NewServer() *Server {
s := &Server{
}
s.Id = uuid.New().String()
return s
}
type Server struct {
SharedOptions
OneOff *bool
ExitCode *int
Running bool
outputStream io.ReadCloser
errorStream io.ReadCloser
}
func (s *Server) Start() (err error) {
exit := make(chan int, 0)
err = Execute(fmt.Sprintf("%s -s", binaryLocation), s.outputStream, s.errorStream, exit)
if err != nil {
return err
}
s.Running = true
go func() {
ds := DebugScanner{}
ds.Scan(s.outputStream)
}()
go func() {
ds := DebugScanner{}
ds.Scan(s.errorStream)
}()
go func() {
exitCode := <- exit
s.ExitCode = &exitCode
s.Running = false
}()
return nil
}
func (s *Server) Stop() {
}

@ -0,0 +1,31 @@
package iperf
import (
"bufio"
"fmt"
"io"
)
type SharedOptions struct {
Id string
Port *int
Format *rune
Interval *int
}
type DebugScanner struct {
}
func (ds *DebugScanner) Scan(buff io.ReadCloser) {
if buff == nil {
fmt.Println("unable to read, ReadCloser is nil")
return
}
scanner := bufio.NewScanner(buff)
scanner.Split(bufio.ScanWords)
for scanner.Scan() {
text := scanner.Text()
fmt.Println(text)
}
}
Loading…
Cancel
Save