add control wrapper
This commit is contained in:
15
.idea/workspace.xml
generated
15
.idea/workspace.xml
generated
@@ -2,7 +2,20 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="fc2840de-29dc-4fca-8e0e-a283562f60ca" name="Default Changelist" comment="">
|
<list default="true" id="fc2840de-29dc-4fca-8e0e-a283562f60ca" name="Default Changelist" comment="">
|
||||||
|
<change afterPath="$PROJECT_DIR$/api/Dockerfile" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/api/build.sh" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/api/proto/control.proto" afterDir="false" />
|
||||||
|
<change afterPath="$PROJECT_DIR$/controller.go" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/README.md" beforeDir="false" afterPath="$PROJECT_DIR$/README.md" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/client.go" beforeDir="false" afterPath="$PROJECT_DIR$/client.go" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/cmd/main.go" beforeDir="false" afterPath="$PROJECT_DIR$/cmd/main.go" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/reporter.go" beforeDir="false" afterPath="$PROJECT_DIR$/reporter.go" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/reporter.go" beforeDir="false" afterPath="$PROJECT_DIR$/reporter.go" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/reporter_linux.go" beforeDir="false" afterPath="$PROJECT_DIR$/reporter_linux.go" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/reporter_windows.go" beforeDir="false" afterPath="$PROJECT_DIR$/reporter_windows.go" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/server.go" beforeDir="false" afterPath="$PROJECT_DIR$/server.go" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/shared.go" beforeDir="false" afterPath="$PROJECT_DIR$/shared.go" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/tests/client/client.go" beforeDir="false" afterPath="$PROJECT_DIR$/tests/client/client.go" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -37,7 +50,7 @@
|
|||||||
<property name="go.import.settings.migrated" value="true" />
|
<property name="go.import.settings.migrated" value="true" />
|
||||||
<property name="go.sdk.automatically.set" value="true" />
|
<property name="go.sdk.automatically.set" value="true" />
|
||||||
<property name="go.tried.to.enable.integration.vgo.integrator" value="true" />
|
<property name="go.tried.to.enable.integration.vgo.integrator" value="true" />
|
||||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
<property name="last_opened_file_path" value="$PROJECT_DIR$/../ran_onf/onos-ric-master/cmd/apps/onos-ric-mlb/onos-ran-mlb.go" />
|
||||||
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
|
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
|
||||||
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
|
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
77
README.md
77
README.md
@@ -1,6 +1,81 @@
|
|||||||
# go-iperf
|
# go-iperf
|
||||||
A Go based wrapper around iperf3
|
A Go based wrapper around iperf3
|
||||||
|
|
||||||
|
## Basic Usage
|
||||||
|
|
||||||
|
basic client setup
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
c := iperf.NewClient("192.168.0.10")
|
||||||
|
c.SetJSON(true)
|
||||||
|
c.SetIncludeServer(true)
|
||||||
|
c.SetStreams(4)
|
||||||
|
c.SetTimeSec(30)
|
||||||
|
c.SetInterval(1)
|
||||||
|
|
||||||
|
err := c.Start()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to start client: %v\n", err)
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
<- c.Done
|
||||||
|
|
||||||
|
fmt.Println(c.Report().String())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
basic server setup
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
s := iperf.NewServer()
|
||||||
|
err := s.Start()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to start server: %v\n", err)
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
for s.Running() {
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("server finished")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
client with live results printing
|
||||||
|
```go
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
c := iperf.NewClient("192.168.0.10")
|
||||||
|
c.SetJSON(true)
|
||||||
|
c.SetIncludeServer(true)
|
||||||
|
c.SetStreams(4)
|
||||||
|
c.SetTimeSec(30)
|
||||||
|
c.SetInterval(1)
|
||||||
|
liveReports := c.SetModeLive()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for report := range liveReports {
|
||||||
|
fmt.Println(report.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := c.Start()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("failed to start client: %v\n", err)
|
||||||
|
os.Exit(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
<- c.Done
|
||||||
|
|
||||||
|
fmt.Println(c.Report().String())
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
building binary data package with iperf binaries
|
||||||
|
```
|
||||||
|
go-bindata -pkg iperf -prefix "embedded/" embedded/
|
||||||
```
|
```
|
||||||
go-bindata -pkg iperf -prefix "embedded/" embedded/```
|
|
||||||
|
|||||||
21
api/Dockerfile
Normal file
21
api/Dockerfile
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# Dockerfile.protogen
|
||||||
|
FROM golang:latest
|
||||||
|
|
||||||
|
LABEL maintainer="Benjamin Grewell <bgrewell@gmail.com>"
|
||||||
|
|
||||||
|
ENV PROTOC_VERSION 3.6.1
|
||||||
|
ENV PROTOC_GEN_GO_VERSION v1.2.0
|
||||||
|
|
||||||
|
WORKDIR /go/src/github.com/BGrewell/go-iperf/api/proto
|
||||||
|
|
||||||
|
RUN apt update
|
||||||
|
RUN apt install -y protobuf-compiler python3 python3-pip
|
||||||
|
RUN go get -u github.com/golang/protobuf/protoc-gen-go
|
||||||
|
RUN pip3 install grpcio-tools
|
||||||
|
RUN export PATH=$PATH:$GOPATH/bin
|
||||||
|
RUN echo $PATH
|
||||||
|
|
||||||
|
COPY proto/control.proto control.proto
|
||||||
|
|
||||||
|
RUN mkdir go
|
||||||
|
RUN protoc -I /. --go_out=plugins=grpc:go control.proto
|
||||||
22
api/build.sh
Normal file
22
api/build.sh
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
if [ ! -d go ]; then
|
||||||
|
echo "[!] Creating go output directory"
|
||||||
|
mkdir go;
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[+] Building docker container"
|
||||||
|
docker image build -t go-iperf-builder:1.0 .
|
||||||
|
docker container run --detach --name builder go-iperf-builder:1.0
|
||||||
|
docker cp grpc:/go/src/github.com/BGrewell/go-iperf/api/go/api.pb.go go/.
|
||||||
|
echo "[+] Updating of go library complete"
|
||||||
|
|
||||||
|
echo "[+] Removing docker container"
|
||||||
|
docker rm builder
|
||||||
|
|
||||||
|
echo "[+] Adding new files to source control"
|
||||||
|
git add go/api.pb.go
|
||||||
|
git commit -m "regenerated grpc libraries"
|
||||||
|
git push
|
||||||
|
|
||||||
|
echo "[+] Done. Everything has been rebuilt and the repository has been updated and pushed"
|
||||||
27
api/proto/control.proto
Normal file
27
api/proto/control.proto
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "google/protobuf/empty.proto";
|
||||||
|
|
||||||
|
// [START java_declaration]
|
||||||
|
option java_multiple_files = true;
|
||||||
|
option java_package = "com.bengrewell.go-iperf.control";
|
||||||
|
option java_outer_classname = "Control";
|
||||||
|
// [END java_declaration]
|
||||||
|
|
||||||
|
// [START csharp_declaration]
|
||||||
|
option csharp_namespace = "BenGrewell.GoIperf.Control";
|
||||||
|
// [END csharp_declaration]
|
||||||
|
|
||||||
|
package api;
|
||||||
|
|
||||||
|
service Command {
|
||||||
|
rpc StartServer(StartServerRequest) returns (StartServerResponse) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
message StartServerRequest {
|
||||||
|
}
|
||||||
|
|
||||||
|
message StartServerResponse {
|
||||||
|
string id = 1;
|
||||||
|
int32 listen_port = 2;
|
||||||
|
}
|
||||||
@@ -62,9 +62,9 @@ type ClientOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
Id string `json:"id" yaml:"id" xml:"id"`
|
Id string `json:"id" yaml:"id" xml:"id"`
|
||||||
Running bool `json:"running" yaml:"running" xml:"running"`
|
Running bool `json:"running" yaml:"running" xml:"running"`
|
||||||
Done chan bool `json:"-" yaml:"-" xml:"-"`
|
Done chan bool `json:"-" yaml:"-" xml:"-"`
|
||||||
Options *ClientOptions `json:"options" yaml:"options" xml:"options"`
|
Options *ClientOptions `json:"options" yaml:"options" xml:"options"`
|
||||||
exitCode *int
|
exitCode *int
|
||||||
report *TestReport
|
report *TestReport
|
||||||
@@ -487,7 +487,6 @@ func (c *Client) SetModeLive() <-chan *StreamIntervalReport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Start() (err error) {
|
func (c *Client) Start() (err error) {
|
||||||
//todo: Need to build the string based on the Options above that are set
|
|
||||||
cmd, err := c.commandString()
|
cmd, err := c.commandString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
26
controller.go
Normal file
26
controller.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package iperf
|
||||||
|
|
||||||
|
type Controller struct {
|
||||||
|
clients map[string]*Client
|
||||||
|
servers map[string]*Server
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) StartListener() (err error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) StopListener() (err error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) StopServer(id string) (err error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) NewServer() (server *Server, err error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) NewClient(serverAddr string) (client *Client, err error) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ type Reporter struct {
|
|||||||
ReportingChannel chan *StreamIntervalReport
|
ReportingChannel chan *StreamIntervalReport
|
||||||
LogFile string
|
LogFile string
|
||||||
running bool
|
running bool
|
||||||
tailer *tail.Tail
|
tailer *tail.Tail
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Reporter) Start() {
|
func (r *Reporter) Start() {
|
||||||
|
|||||||
@@ -59,70 +59,70 @@ func (r *Reporter) runLogProcessor() {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case line := <- r.tailer.Lines:
|
case line := <-r.tailer.Lines:
|
||||||
if line == nil {
|
if line == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if len(line.Text) > 5 {
|
||||||
|
id := line.Text[1:4]
|
||||||
|
stream, err := strconv.Atoi(strings.TrimSpace(id))
|
||||||
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(line.Text) > 5 {
|
fields := strings.Fields(line.Text[5:])
|
||||||
id := line.Text[1:4]
|
if len(fields) >= 9 {
|
||||||
stream, err := strconv.Atoi(strings.TrimSpace(id))
|
if fields[0] == "local" {
|
||||||
if err != nil {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fields := strings.Fields(line.Text[5:])
|
timeFields := strings.Split(fields[0], "-")
|
||||||
if len(fields) >= 9 {
|
start, err := strconv.ParseFloat(timeFields[0], 32)
|
||||||
if fields[0] == "local" {
|
if err != nil {
|
||||||
continue
|
log.Printf("failed to convert start time: %s\n", err)
|
||||||
}
|
|
||||||
timeFields := strings.Split(fields[0], "-")
|
|
||||||
start, err := strconv.ParseFloat(timeFields[0], 32)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("failed to convert start time: %s\n", err)
|
|
||||||
}
|
|
||||||
end, err := strconv.ParseFloat(timeFields[1], 32)
|
|
||||||
transferedStr := fmt.Sprintf("%s%s", fields[2], fields[3])
|
|
||||||
transferedBytes, err := conversions.StringBitRateToInt(transferedStr)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("failed to convert units: %s\n", err)
|
|
||||||
}
|
|
||||||
transferedBytes = transferedBytes / 8
|
|
||||||
rateStr := fmt.Sprintf("%s%s", fields[4], fields[5])
|
|
||||||
rate, err := conversions.StringBitRateToInt(rateStr)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("failed to convert units: %s\n", err)
|
|
||||||
}
|
|
||||||
retrans, err := strconv.Atoi(fields[6])
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("failed to convert units: %s\n", err)
|
|
||||||
}
|
|
||||||
cwndStr := fmt.Sprintf("%s%s", fields[7], fields[8])
|
|
||||||
cwnd, err := conversions.StringBitRateToInt(cwndStr)
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("failed to convert units: %s\n", err)
|
|
||||||
}
|
|
||||||
cwnd = cwnd / 8
|
|
||||||
omitted := false
|
|
||||||
if len(fields) >= 10 && fields[9] == "(omitted)" {
|
|
||||||
omitted = true
|
|
||||||
}
|
|
||||||
report := &StreamIntervalReport{
|
|
||||||
Socket: stream,
|
|
||||||
StartInterval: float32(start),
|
|
||||||
EndInterval: float32(end),
|
|
||||||
Seconds: float32(end - start),
|
|
||||||
Bytes: int(transferedBytes),
|
|
||||||
BitsPerSecond: float64(rate),
|
|
||||||
Retransmissions: retrans,
|
|
||||||
CongestionWindow: int(cwnd),
|
|
||||||
Omitted: omitted,
|
|
||||||
}
|
|
||||||
r.ReportingChannel <- report
|
|
||||||
}
|
}
|
||||||
|
end, err := strconv.ParseFloat(timeFields[1], 32)
|
||||||
|
transferedStr := fmt.Sprintf("%s%s", fields[2], fields[3])
|
||||||
|
transferedBytes, err := conversions.StringBitRateToInt(transferedStr)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to convert units: %s\n", err)
|
||||||
|
}
|
||||||
|
transferedBytes = transferedBytes / 8
|
||||||
|
rateStr := fmt.Sprintf("%s%s", fields[4], fields[5])
|
||||||
|
rate, err := conversions.StringBitRateToInt(rateStr)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to convert units: %s\n", err)
|
||||||
|
}
|
||||||
|
retrans, err := strconv.Atoi(fields[6])
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to convert units: %s\n", err)
|
||||||
|
}
|
||||||
|
cwndStr := fmt.Sprintf("%s%s", fields[7], fields[8])
|
||||||
|
cwnd, err := conversions.StringBitRateToInt(cwndStr)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("failed to convert units: %s\n", err)
|
||||||
|
}
|
||||||
|
cwnd = cwnd / 8
|
||||||
|
omitted := false
|
||||||
|
if len(fields) >= 10 && fields[9] == "(omitted)" {
|
||||||
|
omitted = true
|
||||||
|
}
|
||||||
|
report := &StreamIntervalReport{
|
||||||
|
Socket: stream,
|
||||||
|
StartInterval: float32(start),
|
||||||
|
EndInterval: float32(end),
|
||||||
|
Seconds: float32(end - start),
|
||||||
|
Bytes: int(transferedBytes),
|
||||||
|
BitsPerSecond: float64(rate),
|
||||||
|
Retransmissions: retrans,
|
||||||
|
CongestionWindow: int(cwnd),
|
||||||
|
Omitted: omitted,
|
||||||
|
}
|
||||||
|
r.ReportingChannel <- report
|
||||||
}
|
}
|
||||||
case <- time.After(100 * time.Millisecond):
|
}
|
||||||
if !r.running {
|
case <-time.After(100 * time.Millisecond):
|
||||||
return
|
if !r.running {
|
||||||
}
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func (r *Reporter) runLogProcessor() {
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case line := <- r.tailer.Lines:
|
case line := <-r.tailer.Lines:
|
||||||
if line == nil {
|
if line == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ func (r *Reporter) runLogProcessor() {
|
|||||||
r.ReportingChannel <- report
|
r.ReportingChannel <- report
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case <- time.After(100 * time.Millisecond):
|
case <-time.After(100 * time.Millisecond):
|
||||||
if !r.running {
|
if !r.running {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
142
server.go
142
server.go
@@ -2,41 +2,159 @@ package iperf
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"io"
|
"io"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
defaultPort = 5201
|
||||||
|
defaultInterval = 1
|
||||||
|
defaultJSON = true
|
||||||
|
)
|
||||||
|
|
||||||
func NewServer() *Server {
|
func NewServer() *Server {
|
||||||
defaultPort := 5201
|
|
||||||
defaultInterval := 1
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
Port: &defaultPort,
|
Options: &ServerOptions{
|
||||||
Interval: &defaultInterval,
|
Port: &defaultPort,
|
||||||
|
Interval: &defaultInterval,
|
||||||
|
JSON: &defaultJSON,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
s.Id = uuid.New().String()
|
s.Id = uuid.New().String()
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ServerOptions struct {
|
||||||
|
OneOff *bool `json:"one_off" yaml:"one_off" xml:"one_off"`
|
||||||
|
Port *int `json:"port" yaml:"port" xml:"port"`
|
||||||
|
Format *rune `json:"format" yaml:"format" xml:"format"`
|
||||||
|
Interval *int `json:"interval" yaml:"interval" xml:"interval"`
|
||||||
|
JSON *bool `json:"json" yaml:"json" xml:"json"`
|
||||||
|
LogFile *string `json:"log_file" yaml:"log_file" xml:"log_file"`
|
||||||
|
}
|
||||||
|
|
||||||
type Server struct {
|
type Server struct {
|
||||||
Id string `json:"id" yaml:"id" xml:"id"`
|
Id string `json:"id" yaml:"id" xml:"id"`
|
||||||
OneOff *bool `json:"one_off" yaml:"one_off" xml:"one_off"`
|
|
||||||
ExitCode *int `json:"exit_code" yaml:"exit_code" xml:"exit_code"`
|
|
||||||
Port *int `json:"port" yaml:"port" xml:"port"`
|
|
||||||
Format *rune `json:"format" yaml:"format" xml:"format"`
|
|
||||||
Interval *int `json:"interval" yaml:"interval" xml:"interval"`
|
|
||||||
JSON *bool `json:"json" yaml:"json" xml:"json"`
|
|
||||||
LogFile *string `json:"log_file" yaml:"log_file" xml:"log_file"`
|
|
||||||
Running bool `json:"running" yaml:"running" xml:"running"`
|
Running bool `json:"running" yaml:"running" xml:"running"`
|
||||||
|
Options *ServerOptions `json:"-" yaml:"-" xml:"-"`
|
||||||
|
ExitCode *int `json:"exit_code" yaml:"exit_code" xml:"exit_code"`
|
||||||
outputStream io.ReadCloser `json:"output_stream" yaml:"output_stream" xml:"output_stream"`
|
outputStream io.ReadCloser `json:"output_stream" yaml:"output_stream" xml:"output_stream"`
|
||||||
errorStream io.ReadCloser `json:"error_stream" yaml:"error_stream" xml:"error_stream"`
|
errorStream io.ReadCloser `json:"error_stream" yaml:"error_stream" xml:"error_stream"`
|
||||||
cancel context.CancelFunc `json:"cancel" yaml:"cancel" xml:"cancel"`
|
cancel context.CancelFunc `json:"cancel" yaml:"cancel" xml:"cancel"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) LoadOptionsJSON(jsonStr string) (err error) {
|
||||||
|
return json.Unmarshal([]byte(jsonStr), s.Options)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) LoadOptions(options *ServerOptions) {
|
||||||
|
s.Options = options
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) commandString() (cmd string, err error) {
|
||||||
|
builder := strings.Builder{}
|
||||||
|
fmt.Fprintf(&builder, "%s -s", binaryLocation)
|
||||||
|
|
||||||
|
if s.Options.OneOff != nil && s.OneOff() == true {
|
||||||
|
builder.WriteString(" --one-off")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Options.Port != nil {
|
||||||
|
fmt.Fprintf(&builder, " --port %d", s.Port())
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Options.Format != nil {
|
||||||
|
fmt.Fprintf(&builder, " --format %c", s.Format())
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Options.Interval != nil {
|
||||||
|
fmt.Fprintf(&builder, " --interval %d", s.Interval())
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Options.JSON != nil && s.JSON() == true {
|
||||||
|
builder.WriteString(" --json")
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Options.LogFile != nil && s.LogFile() != "" {
|
||||||
|
fmt.Fprintf(&builder, " --logfile %s --forceflush", s.LogFile())
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) OneOff() bool {
|
||||||
|
if s.Options.OneOff == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return *s.Options.OneOff
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetOneOff(oneOff bool) {
|
||||||
|
s.Options.OneOff = &oneOff
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Port() int {
|
||||||
|
if s.Options.Port == nil {
|
||||||
|
return defaultPort
|
||||||
|
}
|
||||||
|
return *s.Options.Port
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetPort(port int) {
|
||||||
|
s.Options.Port = &port
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Format() rune {
|
||||||
|
if s.Options.Format == nil {
|
||||||
|
return ' '
|
||||||
|
}
|
||||||
|
return *s.Options.Format
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetFormat(format rune) {
|
||||||
|
s.Options.Format = &format
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Interval() int {
|
||||||
|
if s.Options.Interval == nil {
|
||||||
|
return defaultInterval
|
||||||
|
}
|
||||||
|
return *s.Options.Interval
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) JSON() bool {
|
||||||
|
if s.Options.JSON == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return *s.Options.JSON
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetJSON(json bool) {
|
||||||
|
s.Options.JSON = &json
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) LogFile() string {
|
||||||
|
if s.Options.LogFile == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return *s.Options.LogFile
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) SetLogFile(filename string) {
|
||||||
|
s.Options.LogFile = &filename
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) Start() (err error) {
|
func (s *Server) Start() (err error) {
|
||||||
|
cmd, err := s.commandString()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
var exit chan int
|
var exit chan int
|
||||||
s.outputStream, s.errorStream, exit, s.cancel, err = ExecuteAsyncWithCancel(fmt.Sprintf("%s -s -J", binaryLocation))
|
s.outputStream, s.errorStream, exit, s.cancel, err = ExecuteAsyncWithCancel(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user