182 lines
4.1 KiB
Go
182 lines
4.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"net"
|
|
"os"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var spotRe *regexp.Regexp = regexp.MustCompile(`DX\sde\s([\w\d]+).*:\s+(\d+.\d)\s+([\w\d\/]+)\s+(CW|SSB|FT8|FT4|RTTY|USB|LSB)?\s+(.*)\s\s\s+([\d]+\w{1})`)
|
|
|
|
type TCPClient struct {
|
|
Login string
|
|
Password string
|
|
Address string
|
|
Port string
|
|
Timeout time.Duration
|
|
LogWriter *bufio.Writer
|
|
Reader *bufio.Reader
|
|
Writer *bufio.Writer
|
|
Conn *net.TCPConn
|
|
TCPServer TCPServer
|
|
MsgChan chan string
|
|
CmdChan chan string
|
|
SpotChanToFlex chan TelnetSpot
|
|
SpotChanToHTTPServer chan TelnetSpot
|
|
Log *log.Logger
|
|
Config *Config
|
|
Countries Countries
|
|
}
|
|
|
|
func NewTCPClient(TCPServer *TCPServer, Countries Countries) *TCPClient {
|
|
return &TCPClient{
|
|
Address: Cfg.Cluster.Server,
|
|
Port: Cfg.Cluster.Port,
|
|
Login: Cfg.Cluster.Login,
|
|
MsgChan: TCPServer.MsgChan,
|
|
CmdChan: TCPServer.CmdChan,
|
|
SpotChanToFlex: make(chan TelnetSpot, 100),
|
|
TCPServer: *TCPServer,
|
|
SpotChanToHTTPServer: make(chan TelnetSpot, 100),
|
|
Countries: Countries,
|
|
}
|
|
}
|
|
|
|
func (c *TCPClient) setDefaultParams() {
|
|
if c.Timeout == 0 {
|
|
c.Timeout = 600 * time.Second
|
|
}
|
|
if c.LogWriter == nil {
|
|
c.LogWriter = bufio.NewWriter(os.Stdout)
|
|
}
|
|
}
|
|
|
|
func (c *TCPClient) StartClient() {
|
|
var err error
|
|
|
|
addr, err := net.ResolveTCPAddr("tcp", c.Address+":"+c.Port)
|
|
if err != nil {
|
|
Log.Error("Cannot resolve Telnet Client address:", err)
|
|
}
|
|
|
|
c.setDefaultParams()
|
|
c.Conn, err = net.DialTCP("tcp", nil, addr)
|
|
if err != nil {
|
|
Log.Error("Cannot connect to Telnet Client:", err)
|
|
}
|
|
Log.Infof("Connected to DX cluster %s:%s", c.Address, c.Port)
|
|
|
|
err = c.Conn.SetKeepAlive(true)
|
|
if err != nil {
|
|
Log.Error("Error while setting keep alive:", err)
|
|
}
|
|
|
|
c.Reader = bufio.NewReader(c.Conn)
|
|
c.Writer = bufio.NewWriter(c.Conn)
|
|
|
|
go func() {
|
|
for message := range c.TCPServer.CmdChan {
|
|
Log.Infof("Received DX Command: %s", message)
|
|
message := message + "\n"
|
|
c.WriteString(message)
|
|
}
|
|
}()
|
|
|
|
go c.ReadLine()
|
|
}
|
|
|
|
func (c *TCPClient) Close() {
|
|
c.Writer.WriteString("bye")
|
|
time.Sleep(time.Second * 2)
|
|
}
|
|
|
|
func (c *TCPClient) SetFilters() {
|
|
if Cfg.Cluster.FT8 {
|
|
c.Write([]byte("set/ft8\r\n"))
|
|
Log.Info("FT8: On")
|
|
}
|
|
|
|
if Cfg.Cluster.Skimmer {
|
|
c.Write([]byte("set/skimmer\r\n"))
|
|
Log.Info("Skimmer: On")
|
|
}
|
|
|
|
if Cfg.Cluster.FT4 {
|
|
c.Write([]byte("set/ft4\r\n"))
|
|
Log.Info("FT4: On")
|
|
}
|
|
|
|
if !Cfg.Cluster.FT8 {
|
|
c.Write([]byte("set/noft8\r\n"))
|
|
Log.Info("FT8: Off")
|
|
}
|
|
|
|
if !Cfg.Cluster.FT4 {
|
|
c.Write([]byte("set/noft4\r\n"))
|
|
Log.Info("FT4: Off")
|
|
}
|
|
|
|
if !Cfg.Cluster.Skimmer {
|
|
c.Write([]byte("set/noskimmer\r\n"))
|
|
Log.Info("Skimmer: Off")
|
|
}
|
|
}
|
|
|
|
func (c *TCPClient) ReadLine() {
|
|
|
|
for {
|
|
message, err := c.Reader.ReadString('\n')
|
|
message, _ = strings.CutSuffix(message, "\n")
|
|
message, _ = strings.CutSuffix(message, "\r")
|
|
if err != nil {
|
|
Log.Errorf("Error reading message: %s", err)
|
|
c.Conn.Close()
|
|
c.StartClient()
|
|
}
|
|
|
|
if strings.Contains(message, Cfg.Cluster.LoginPrompt) {
|
|
Log.Debug("Found login prompt...sending callsign")
|
|
c.Write([]byte(c.Login + "\r\n"))
|
|
c.SetFilters()
|
|
if Cfg.Cluster.Command != "" {
|
|
c.WriteString(Cfg.Cluster.Command)
|
|
}
|
|
Log.Info("Start receiving spots")
|
|
} else if strings.Contains(message, "Error reading from server: read tcp") {
|
|
Log.Error("Disconnected from Telnet Server, reconnecting")
|
|
c.Close()
|
|
c.StartClient()
|
|
} else {
|
|
ProcessTelnetSpot(spotRe, message, c.SpotChanToFlex, c.SpotChanToHTTPServer, c.Countries)
|
|
}
|
|
|
|
// Send the spot message to TCP server
|
|
c.MsgChan <- message
|
|
|
|
}
|
|
}
|
|
|
|
// Write sends raw data to remove telnet server
|
|
func (tc *TCPClient) Write(data []byte) (n int, err error) {
|
|
n, err = tc.Writer.Write(data)
|
|
if err == nil {
|
|
err = tc.Writer.Flush()
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (tc *TCPClient) WriteString(data string) (n int, err error) {
|
|
n, err = tc.Writer.Write([]byte(data))
|
|
if err == nil {
|
|
err = tc.Writer.Flush()
|
|
}
|
|
|
|
return
|
|
}
|