Add ping2
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
package cmpSnipper
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
"strconv"
|
||||
"os/exec"
|
||||
"context"
|
||||
"time"
|
||||
@@ -9,6 +12,12 @@
|
||||
"syscall"
|
||||
)
|
||||
|
||||
type Ping2Struct struct {
|
||||
Addr string
|
||||
Win string
|
||||
Pid int
|
||||
}
|
||||
|
||||
func (app *App) PingSnip(parm any) (any, error) {
|
||||
// log.Println("PingSnip")
|
||||
|
||||
@@ -68,3 +77,357 @@
|
||||
"stderr" : stderr.String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
func (app *App) copyAndCapture(r io.Reader, strWin string) ([]byte, error) {
|
||||
var out []byte
|
||||
buf := make([]byte, 1024, 1024)
|
||||
for {
|
||||
n, err := r.Read(buf[:])
|
||||
if n > 0 {
|
||||
d := buf[:n]
|
||||
out = append(out, d...)
|
||||
str := strings.Trim(string(d), "\n\r")
|
||||
|
||||
app.Log("Std: %s", str)
|
||||
|
||||
app.Ping2SendStr(str)
|
||||
}
|
||||
if err != nil {
|
||||
// Read returns io.EOF at the end of file, which is not an error for us
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (app *App) Ping2SendObj(obj map[string]interface{}) (error) {
|
||||
if app.CliCur == nil {
|
||||
app.Log("No cli")
|
||||
return nil
|
||||
}
|
||||
|
||||
app.HttpWebSockSendTo(*app.CliCur, "ping2Data", obj)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (app *App) Ping2SendStr(str string) (error) {
|
||||
return app.Ping2SendObj(map[string]interface{}{
|
||||
"data" : "stdout",
|
||||
"string": str,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func (app *App) ping2Capture(r io.Reader, strWin string) ([]byte, error) {
|
||||
var out []byte
|
||||
buf := make([]byte, 1024, 1024)
|
||||
for {
|
||||
n, err := r.Read(buf[:])
|
||||
if n > 0 {
|
||||
d := buf[:n]
|
||||
out = append(out, d...)
|
||||
str := strings.Trim(string(d), "\n\r")
|
||||
|
||||
app.Log("Std: %s", str)
|
||||
|
||||
app.Ping2SendStr(str)
|
||||
}
|
||||
if err != nil {
|
||||
// Read returns io.EOF at the end of file, which is not an error for us
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
return out, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (app *App) Ping2ExecStart(strAddr string, strWin string) (any, error) {
|
||||
var Ping2Free *Ping2Struct = nil
|
||||
|
||||
for key, val := range app.Ping2List {
|
||||
if val.Pid == 0 {
|
||||
Ping2Free = &val
|
||||
break
|
||||
}
|
||||
|
||||
if val.Addr == strAddr {
|
||||
app.Ping2List[key].Win = strWin
|
||||
|
||||
return map[string]interface{}{
|
||||
"stutus" : "success",
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
if Ping2Free == nil {
|
||||
var NewPing2Struct Ping2Struct
|
||||
Ping2Free = &NewPing2Struct
|
||||
app.Ping2List = append(app.Ping2List, NewPing2Struct)
|
||||
}
|
||||
|
||||
var err error
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 100 * time.Second)
|
||||
|
||||
defer cancel()
|
||||
|
||||
cmd := exec.CommandContext(ctx, "ping", "-c", "40", strAddr)
|
||||
|
||||
var stdout, stderr []byte
|
||||
stdoutIn, _ := cmd.StdoutPipe()
|
||||
stderrIn, _ := cmd.StderrPipe()
|
||||
|
||||
var exitCode int;
|
||||
|
||||
err = cmd.Start()
|
||||
|
||||
if err != nil {
|
||||
app.Log(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Ping2Free.Addr = strAddr
|
||||
Ping2Free.Win = strWin
|
||||
Ping2Free.Pid = cmd.Process.Pid
|
||||
|
||||
go app.Ping2SendObj(map[string]interface{}{
|
||||
"data" : "procid",
|
||||
"procid": Ping2Free.Pid,
|
||||
})
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
stdout, err = app.ping2Capture(stdoutIn, strWin)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
stderr, err = app.ping2Capture(stderrIn, strWin)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
err = cmd.Wait()
|
||||
|
||||
if err != nil {
|
||||
// try to get the exit code
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
ws := exitError.Sys().(syscall.WaitStatus)
|
||||
exitCode = ws.ExitStatus()
|
||||
} else {
|
||||
// This will happen (in OSX) if `name` is not available in $PATH,
|
||||
// in this situation, exit code could not be get, and stderr will be
|
||||
// empty string very likely, so we use the default fail code, and format err
|
||||
// to string and set to stderr
|
||||
|
||||
app.Log("Could not get exit code for failed program")
|
||||
exitCode = 255
|
||||
}
|
||||
} else {
|
||||
// success, exitCode should be 0 if go is ok
|
||||
ws := cmd.ProcessState.Sys().(syscall.WaitStatus)
|
||||
exitCode = ws.ExitStatus()
|
||||
}
|
||||
|
||||
app.Log("Exit code %s", exitCode)
|
||||
|
||||
if false { /* ??? */
|
||||
outStr, errStr := string(stdout), string(stderr)
|
||||
app.Log("\nout:\n%s\nerr:\n%s\n", outStr, errStr)
|
||||
}
|
||||
|
||||
Ping2Free.Pid = 0
|
||||
|
||||
return map[string]interface{}{
|
||||
"stutus" : "error",
|
||||
"error" : "Invalid IPv4 address",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (app *App) Ping2ExecSign(strAddr string, strWin string, strSign string) (any, error) {
|
||||
for _, val := range app.Ping2List {
|
||||
if val.Pid == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if val.Addr != strAddr {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
var err error
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 100 * time.Second)
|
||||
|
||||
defer cancel()
|
||||
|
||||
pidStr := strconv.Itoa(val.Pid)
|
||||
|
||||
app.Log("kill %s", pidStr)
|
||||
|
||||
cmd := exec.CommandContext(ctx, "kill", strSign, pidStr)
|
||||
|
||||
var exitCode int;
|
||||
|
||||
err = cmd.Run()
|
||||
|
||||
if err != nil {
|
||||
// try to get the exit code
|
||||
if exitError, ok := err.(*exec.ExitError); ok {
|
||||
ws := exitError.Sys().(syscall.WaitStatus)
|
||||
exitCode = ws.ExitStatus()
|
||||
} else {
|
||||
// This will happen (in OSX) if `name` is not available in $PATH,
|
||||
// in this situation, exit code could not be get, and stderr will be
|
||||
// empty string very likely, so we use the default fail code, and format err
|
||||
// to string and set to stderr
|
||||
|
||||
app.Log("Could not get exit code for failed program")
|
||||
exitCode = 255
|
||||
}
|
||||
} else {
|
||||
// success, exitCode should be 0 if go is ok
|
||||
ws := cmd.ProcessState.Sys().(syscall.WaitStatus)
|
||||
exitCode = ws.ExitStatus()
|
||||
}
|
||||
|
||||
app.Log("Exit code %s", exitCode)
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
return map[string]interface{}{
|
||||
"stutus" : "success",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (app *App) Ping2ExecStop(strAddr string, strWin string) (any, error) {
|
||||
return app.Ping2ExecSign(strAddr, strWin, "-SIGINT")
|
||||
}
|
||||
|
||||
func (app *App) Ping2ExecStat(strAddr string, strWin string) (any, error) {
|
||||
return app.Ping2ExecSign(strAddr, strWin, "-SIGQUIT")
|
||||
}
|
||||
|
||||
|
||||
func (app *App) Ping2ExecSnip(parm any) (any, error) {
|
||||
var err error
|
||||
var ok bool
|
||||
|
||||
var ifcAddr interface{}
|
||||
var ifcCmd interface{}
|
||||
var ifcWin interface{}
|
||||
|
||||
ifcAddr, err = app.IfcGet(parm, "InputArgument", "addr")
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"stutus" : "error",
|
||||
"error" : "Unset IPv4 address",
|
||||
}, nil
|
||||
}
|
||||
|
||||
ifcCmd, err = app.IfcGet(parm, "InputArgument", "cmd")
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"stutus" : "error",
|
||||
"error" : "Unset command",
|
||||
}, nil
|
||||
}
|
||||
|
||||
ifcWin, err = app.IfcGet(parm, "InputArgument", "win")
|
||||
|
||||
if err != nil {
|
||||
return map[string]interface{}{
|
||||
"stutus" : "error",
|
||||
"error" : "Unset window",
|
||||
}, nil
|
||||
}
|
||||
|
||||
var strAddr string
|
||||
var strCmd string
|
||||
var strWin string
|
||||
|
||||
strAddr, ok = ifcAddr.(string)
|
||||
|
||||
if !ok {
|
||||
return map[string]interface{}{
|
||||
"stutus" : "error",
|
||||
"error" : "Invalid IPv4 address type",
|
||||
}, nil
|
||||
}
|
||||
|
||||
strCmd, ok = ifcCmd.(string)
|
||||
|
||||
if !ok {
|
||||
return map[string]interface{}{
|
||||
"stutus" : "error",
|
||||
"error" : "Invalid command type",
|
||||
}, nil
|
||||
}
|
||||
|
||||
strWin, ok = ifcWin.(string)
|
||||
|
||||
if !ok {
|
||||
intWin, ok := ifcWin.(float64)
|
||||
|
||||
if !ok {
|
||||
return map[string]interface{}{
|
||||
"stutus" : "error",
|
||||
"error" : "Invalid window type",
|
||||
}, nil
|
||||
}
|
||||
|
||||
strWin = strconv.FormatFloat(intWin, 'f', -1, 32)
|
||||
}
|
||||
|
||||
|
||||
switch(strAddr) {
|
||||
case "1.1.1.1":
|
||||
break;
|
||||
case "8.8.8.8":
|
||||
break;
|
||||
case "8.8.4.4":
|
||||
break;
|
||||
case "9.9.9.9":
|
||||
break;
|
||||
|
||||
default:
|
||||
return map[string]interface{}{
|
||||
"stutus" : "error",
|
||||
"error" : "Invalid IPv4 address",
|
||||
}, nil
|
||||
}
|
||||
|
||||
switch(strCmd) {
|
||||
case "start":
|
||||
go app.Ping2ExecStart(strAddr, strWin)
|
||||
|
||||
return map[string]interface{}{
|
||||
"status" : "success",
|
||||
}, nil
|
||||
|
||||
case "stop":
|
||||
return app.Ping2ExecStop(strAddr, strWin)
|
||||
|
||||
case "stat":
|
||||
return app.Ping2ExecStat(strAddr, strWin)
|
||||
|
||||
default:
|
||||
return map[string]interface{}{
|
||||
"stutus" : "error",
|
||||
"error" : "Invalid command",
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user