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})`) var count int = 0 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 FlexClient FlexClient MsgChan chan string CmdChan chan string SpotChan chan TelnetSpot Log *log.Logger } func NewTCPClient(cfg Config, TCPServer *TCPServer, FlexClient *FlexClient, log *log.Logger) *TCPClient { return &TCPClient{ Address: Cfg.Cluster.Server, Port: Cfg.Cluster.Port, Login: Cfg.Cluster.Login, MsgChan: TCPServer.MsgChan, CmdChan: TCPServer.CmdChan, SpotChan: FlexClient.SpotChan, Log: log, TCPServer: *TCPServer, FlexClient: *FlexClient, } } 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 { c.Log.Error("cannot resolve Telnet Client address:", err) } c.setDefaultParams() c.Conn, err = net.DialTCP("tcp", nil, addr) if err != nil { c.Log.Error("cannot connect to Telnet Client:", err) } c.Log.Infof("connected to DX cluster %s:%s", c.Address, c.Port) err = c.Conn.SetKeepAlive(true) if err != nil { c.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 { c.Log.Infof("Received DX Command: %s", message) message := message + "\n" c.WriteString(message) } }() go c.ReadLine() } func (c *TCPClient) Close() { c.Writer.WriteString("bye") } func (c *TCPClient) SetFilters() { if Cfg.Cluster.FT8 { c.Write([]byte("set/ft8\r\n")) c.Log.Info("FT8 is on as defined in the config file") } if Cfg.Cluster.Skimmer { c.Write([]byte("set/skimmer\r\n")) c.Log.Info("Skimmer is on as defined in the config file") } if !Cfg.Cluster.FT8 { c.Write([]byte("set/noft8\r\n")) c.Log.Info("FT8 is off as defined in the config file") } if !Cfg.Cluster.Skimmer { c.Write([]byte("set/noskimmer\r\n")) c.Log.Info("Skimmer is off as defined in the config file") } } func (c *TCPClient) ReadLine() { for { message, err := c.Reader.ReadString('\n') if err != nil { c.Log.Errorf("Error reading message: %s", err) continue } if strings.Contains(message, "Login: \r\n") || strings.Contains(message, "Please enter your call: \r\n") { c.Log.Info("Found login prompt...sending callsign") c.Write([]byte(c.Login + "\r\n")) time.Sleep(time.Second * 2) c.SetFilters() } ProcessTelnetSpot(spotRe, message, c.SpotChan, c.Log) // Send the spot message to TCP server if len(c.TCPServer.Clients) > 0 { if count == 0 { // wait 3 seconds before sending messages to allow the client to connect time.Sleep(time.Second * 3) count++ } 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 }