pat/listen.go
2023-05-21 23:35:13 +02:00

221 lines
5.4 KiB
Go

// Copyright 2016 Martin Hebnes Pedersen (LA5NTA). All rights reserved.
// Use of this source code is governed by the MIT-license that can be
// found in the LICENSE file.
package main
import (
"context"
"log"
"net"
"strings"
"time"
"github.com/la5nta/wl2k-go/transport/ax25"
"github.com/la5nta/wl2k-go/transport/telnet"
)
func Unlisten(param string) {
methods := strings.FieldsFunc(param, SplitFunc)
for _, method := range methods {
ok, err := listenHub.Disable(method)
if err != nil {
log.Printf("Unable to close %s listener: %s", method, err)
} else if !ok {
log.Printf("No active %s listener, ignoring.\n", method)
}
}
}
func Listen(listenStr string) {
methods := strings.FieldsFunc(listenStr, SplitFunc)
for _, method := range methods {
// Rewrite the generic ax25:// scheme to use a specified AX.25 engine.
if method == MethodAX25 {
method = defaultAX25Method()
}
switch strings.ToLower(method) {
case MethodArdop:
listenHub.Enable(ARDOPListener{})
case MethodTelnet:
listenHub.Enable(TelnetListener{})
case MethodAX25AGWPE:
listenHub.Enable(&AX25AGWPEListener{})
case MethodAX25Linux:
listenHub.Enable(&AX25LinuxListener{})
case MethodVaraFM:
listenHub.Enable(VaraFMListener{})
case MethodVaraHF:
listenHub.Enable(VaraHFListener{})
case MethodAX25SerialTNC, MethodSerialTNCDeprecated:
log.Printf("%s listen not implemented, ignoring.", method)
default:
log.Printf("'%s' is not a valid listen method", method)
return
}
}
log.Printf("Listening for incoming traffic on %s...", listenStr)
}
type AX25LinuxListener struct{ stopBeacon func() }
func (l *AX25LinuxListener) Init() (net.Listener, error) {
return ax25.ListenAX25(config.AX25Linux.Port, fOptions.MyCall)
}
func (l *AX25LinuxListener) BeaconStart() error {
interval := time.Duration(config.AX25.Beacon.Every) * time.Second
if interval == 0 {
return nil
}
b, err := ax25.NewAX25Beacon(config.AX25Linux.Port, fOptions.MyCall, config.AX25.Beacon.Destination, config.AX25.Beacon.Message)
if err != nil {
return err
}
l.stopBeacon = doEvery(interval, func() {
if err := b.Now(); err != nil {
log.Printf("%s beacon failed: %s", l.Name(), err)
l.stopBeacon()
}
})
return nil
}
func (l *AX25LinuxListener) BeaconStop() {
if l.stopBeacon != nil {
l.stopBeacon()
}
}
func (l *AX25LinuxListener) CurrentFreq() (Frequency, bool) { return 0, false }
func (l *AX25LinuxListener) Name() string { return MethodAX25Linux }
type ARDOPListener struct{}
func (l ARDOPListener) Name() string { return MethodArdop }
func (l ARDOPListener) Init() (net.Listener, error) {
if err := initArdopTNC(); err != nil {
return nil, err
}
ln, err := adTNC.Listen()
if err != nil {
return nil, err
}
return ln, err
}
func (l ARDOPListener) CurrentFreq() (Frequency, bool) {
if rig, ok := rigs[config.Ardop.Rig]; ok {
f, _ := rig.GetFreq()
return Frequency(f), ok
}
return 0, false
}
func (l ARDOPListener) BeaconStart() error {
return adTNC.BeaconEvery(time.Duration(config.Ardop.BeaconInterval) * time.Second)
}
func (l ARDOPListener) BeaconStop() { adTNC.BeaconEvery(0) }
type VaraFMListener struct{}
func (l VaraFMListener) Name() string { return MethodVaraFM }
func (l VaraFMListener) Init() (net.Listener, error) {
if err := initVaraFMModem(); err != nil {
return nil, err
}
ln, err := varaFMModem.Listen()
if err != nil {
return nil, err
}
return ln, err
}
func (l VaraFMListener) CurrentFreq() (Frequency, bool) {
if rig, ok := rigs[config.VaraFM.Rig]; ok {
f, _ := rig.GetFreq()
return Frequency(f), ok
}
return 0, false
}
type VaraHFListener struct{}
func (l VaraHFListener) Name() string { return MethodVaraHF }
func (l VaraHFListener) Init() (net.Listener, error) {
if err := initVaraHFModem(); err != nil {
return nil, err
}
ln, err := varaHFModem.Listen()
if err != nil {
return nil, err
}
return ln, err
}
func (l VaraHFListener) CurrentFreq() (Frequency, bool) {
if rig, ok := rigs[config.VaraHF.Rig]; ok {
f, _ := rig.GetFreq()
return Frequency(f), ok
}
return 0, false
}
type AX25AGWPEListener struct{ stopBeacon func() }
func (l *AX25AGWPEListener) Name() string { return MethodAX25AGWPE }
func (l *AX25AGWPEListener) Init() (net.Listener, error) {
if err := initAGWPE(); err != nil {
return nil, err
}
return agwpeTNC.Listen()
}
func (l *AX25AGWPEListener) CurrentFreq() (Frequency, bool) { return 0, false }
func (l *AX25AGWPEListener) BeaconStart() error {
b := config.AX25.Beacon
interval := time.Duration(b.Every) * time.Second
l.stopBeacon = doEvery(interval, func() {
if err := agwpeTNC.SendUI([]byte(b.Message), b.Destination); err != nil {
log.Printf("%s beacon failed: %s", l.Name(), err)
l.stopBeacon()
}
})
return nil
}
func (l AX25AGWPEListener) BeaconStop() {
if l.stopBeacon != nil {
l.stopBeacon()
}
}
type TelnetListener struct{}
func (l TelnetListener) Name() string { return MethodTelnet }
func (l TelnetListener) Init() (net.Listener, error) { return telnet.Listen(config.Telnet.ListenAddr) }
func (l TelnetListener) CurrentFreq() (Frequency, bool) { return 0, false }
func doEvery(interval time.Duration, fn func()) (cancel func()) {
if interval == 0 {
return
}
ctx, cancel := context.WithCancel(context.Background())
go func() {
t := time.NewTicker(interval)
defer t.Stop()
for {
select {
case <-ctx.Done():
return
case <-t.C:
fn()
}
}
}()
return cancel
}