mirror of
https://github.com/la5nta/pat
synced 2026-08-13 17:46:54 -04:00
221 lines
5.4 KiB
Go
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
|
|
}
|