2022-11-05 18:58:36 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/binary"
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"net"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/BurntSushi/toml"
|
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
host string
|
|
|
|
port int
|
|
|
|
streamname string
|
|
|
|
bps int
|
|
|
|
channel int
|
|
|
|
delay int
|
|
|
|
loglevel int
|
|
|
|
|
|
|
|
bpsOpts = []int{0, 110, 150, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 31250,
|
|
|
|
38400, 57600, 115200, 128000, 230400, 250000, 256000, 460800, 921600,
|
|
|
|
1000000, 1500000, 2000000, 3000000}
|
|
|
|
)
|
|
|
|
|
|
|
|
type (
|
|
|
|
// connection represents the configurable fields of a config.toml
|
|
|
|
connection struct {
|
|
|
|
Host string
|
|
|
|
Port int
|
|
|
|
Streamname string
|
|
|
|
}
|
|
|
|
|
|
|
|
// config maps toml headers
|
|
|
|
config struct {
|
|
|
|
Connection map[string]connection
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func main() {
|
2024-06-28 06:55:53 +01:00
|
|
|
flag.StringVar(&host, "host", "localhost", "vban host")
|
|
|
|
flag.StringVar(&host, "h", "localhost", "vban host (shorthand)")
|
2022-11-05 18:58:36 +00:00
|
|
|
flag.IntVar(&port, "port", 6980, "vban server port")
|
|
|
|
flag.IntVar(&port, "p", 6980, "vban server port (shorthand)")
|
|
|
|
flag.StringVar(&streamname, "streamname", "Command1", "stream name for text requests")
|
|
|
|
flag.StringVar(&streamname, "s", "Command1", "stream name for text requests (shorthand)")
|
|
|
|
flag.IntVar(&bps, "bps", 0, "vban bps")
|
|
|
|
flag.IntVar(&bps, "b", 0, "vban bps (shorthand)")
|
|
|
|
flag.IntVar(&channel, "channel", 0, "vban channel")
|
|
|
|
flag.IntVar(&channel, "c", 0, "vban channel (shorthand)")
|
|
|
|
flag.IntVar(&delay, "delay", 20, "delay between requests")
|
|
|
|
flag.IntVar(&delay, "d", 20, "delay between requests (shorthand)")
|
2024-06-28 06:55:53 +01:00
|
|
|
flag.IntVar(&loglevel, "loglevel", int(log.WarnLevel), "log level")
|
|
|
|
flag.IntVar(&loglevel, "l", int(log.WarnLevel), "log level (shorthand)")
|
2022-11-05 18:58:36 +00:00
|
|
|
flag.Parse()
|
|
|
|
|
2024-06-28 06:55:53 +01:00
|
|
|
if loglevel >= int(log.PanicLevel) && loglevel <= int(log.TraceLevel) {
|
|
|
|
log.SetLevel(log.Level(loglevel))
|
|
|
|
}
|
2022-11-05 18:58:36 +00:00
|
|
|
|
|
|
|
c, err := vbanConnect()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
defer c.Close()
|
|
|
|
|
|
|
|
header := newRequestHeader(streamname, indexOf(bpsOpts, bps), channel)
|
|
|
|
for _, arg := range flag.Args() {
|
|
|
|
err := send(c, header, arg)
|
|
|
|
if err != nil {
|
2024-06-28 06:55:53 +01:00
|
|
|
log.Error(err.Error())
|
2022-11-05 18:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// vbanConnect establishes a VBAN connection to remote host
|
|
|
|
func vbanConnect() (*net.UDPConn, error) {
|
2024-06-28 06:55:53 +01:00
|
|
|
homeDir, err := os.UserHomeDir()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
f := filepath.Join(homeDir, ".vbantxt_cli", "config.toml")
|
|
|
|
if _, err := os.Stat(f); err == nil {
|
|
|
|
conn, err := connFromToml(f)
|
2022-11-05 18:58:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-06-28 06:55:53 +01:00
|
|
|
if !isFlagPassed("h") && !isFlagPassed("host") {
|
|
|
|
host = conn.Host
|
|
|
|
}
|
|
|
|
if !isFlagPassed("p") && !isFlagPassed("port") {
|
|
|
|
port = conn.Port
|
|
|
|
}
|
|
|
|
if !isFlagPassed("s") && !isFlagPassed("streamname") {
|
|
|
|
streamname = conn.Streamname
|
2022-11-05 18:58:36 +00:00
|
|
|
}
|
|
|
|
}
|
2024-06-28 06:55:53 +01:00
|
|
|
log.Debugf("Using values host: %s port: %d streamname: %s", host, port, streamname)
|
2022-11-05 18:58:36 +00:00
|
|
|
|
2024-06-28 06:55:53 +01:00
|
|
|
s, _ := net.ResolveUDPAddr("udp4", fmt.Sprintf("%s:%d", host, port))
|
2022-11-05 18:58:36 +00:00
|
|
|
c, err := net.DialUDP("udp4", nil, s)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-06-28 06:55:53 +01:00
|
|
|
log.Infof("Connected to %s", c.RemoteAddr())
|
2022-11-05 18:58:36 +00:00
|
|
|
|
|
|
|
return c, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// connFromToml parses connection info from config.toml
|
2024-06-28 06:55:53 +01:00
|
|
|
func connFromToml(f string) (*connection, error) {
|
2022-11-05 18:58:36 +00:00
|
|
|
var c config
|
2024-06-28 06:55:53 +01:00
|
|
|
_, err := toml.DecodeFile(f, &c.Connection)
|
2022-11-05 18:58:36 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
conn := c.Connection["connection"]
|
|
|
|
return &conn, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// send sends a VBAN text request over UDP to remote host
|
|
|
|
func send(c *net.UDPConn, h *requestHeader, msg string) error {
|
2024-06-28 06:55:53 +01:00
|
|
|
log.Debugf("Sending '%s' to: %s", msg, c.RemoteAddr())
|
2022-11-05 18:58:36 +00:00
|
|
|
data := []byte(msg)
|
|
|
|
_, err := c.Write(append(h.header(), data...))
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
var a uint32
|
|
|
|
_ = binary.Read(bytes.NewReader(h.framecounter[:]), binary.LittleEndian, &a)
|
|
|
|
binary.LittleEndian.PutUint32(h.framecounter[:], a+1)
|
|
|
|
|
|
|
|
time.Sleep(time.Duration(delay) * time.Millisecond)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|