/
ardop.go
134 lines (118 loc) · 3.74 KB
/
ardop.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2015 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 ardop provides means of establishing a connection to a remote node using ARDOP TNC
package ardop
import (
"errors"
"fmt"
"os"
"strings"
"time"
)
const (
DefaultAddr = "localhost:8515" // The default address Ardop TNC listens on
DefaultARQTimeout = 90 * time.Second // The default ARQ session idle timout
)
const (
ModeARQ = "ARQ" // ARQ mode
ModeFEC = "FEC" // FEC mode
)
// TNC states
const (
//go:generate stringer -type=State .
Unknown State = iota
Offline // Sound card disabled and all sound card resources are released
Disconnected // The session is disconnected, the sound card remains active
ISS // Information Sending Station (Sending Data)
IRS // Information Receiving Station (Receiving data)
Idle // ??
FECSend // ??
FECReceive // Receiving FEC (unproto) data
)
var (
ErrBusy = errors.New("TNC control port is busy.")
ErrConnectInProgress = errors.New("A connect is in progress.")
ErrFlushTimeout = errors.New("Flush timeout.")
ErrActiveListenerExists = errors.New("An active listener is already registered with this TNC.")
ErrDisconnectTimeout = errors.New("Disconnect timeout: aborted connection.")
ErrConnectTimeout = errors.New("Connect timeout")
ErrChecksumMismatch = errors.New("Control protocol checksum mismatch")
ErrTNCClosed = errors.New("TNC closed")
ErrUnsupportedBandwidth = errors.New("Unsupported ARQ bandwidth")
)
// Bandwidth definitions of all supported ARQ bandwidths.
var (
Bandwidth200Max = Bandwidth{false, 200}
Bandwidth500Max = Bandwidth{false, 500}
Bandwidth1000Max = Bandwidth{false, 1000}
Bandwidth2000Max = Bandwidth{false, 2000}
Bandwidth200Forced = Bandwidth{true, 200}
Bandwidth500Forced = Bandwidth{true, 500}
Bandwidth1000Forced = Bandwidth{true, 1000}
Bandwidth2000Forced = Bandwidth{true, 2000}
)
type State uint8
// Bandwidth represents the ARQ bandwidth.
type Bandwidth struct {
Forced bool // Force use of max bandwidth.
Max uint // Max bandwidh to use.
}
// Stringer for Bandwidth returns a valid bandwidth parameter that can be sent to the TNC.
func (bw Bandwidth) String() string {
str := fmt.Sprintf("%d", bw.Max)
if bw.Forced {
str += "FORCED"
} else {
str += "MAX"
}
return str
}
// IsZero returns true if bw is it's zero value.
func (bw Bandwidth) IsZero() bool { return bw.Max == 0 }
// BandwidthFromString returns a Bandwidth representation of the given string.
//
// The string must be a valid ARDOP ARQ bandwidth string (e.g. "2000MAX", "2000FORCED").
// The MAX/FORCED suffix may be omitted. Defaults to MAX.
func BandwidthFromString(str string) (Bandwidth, error) {
// Default to MAX if MAX/FORCED is not given.
if strings.HasSuffix(str, "0") {
str += "MAX"
}
for _, bw := range Bandwidths() {
if bw.String() == str {
return bw, nil
}
}
return Bandwidth{}, ErrUnsupportedBandwidth
}
// Bandwidths returns a list of all ARDOP ARQ bandwidths.
func Bandwidths() []Bandwidth {
return []Bandwidth{
Bandwidth200Max,
Bandwidth500Max,
Bandwidth1000Max,
Bandwidth2000Max,
Bandwidth200Forced,
Bandwidth500Forced,
Bandwidth1000Forced,
Bandwidth2000Forced,
}
}
var stateMap = map[string]State{
"": Unknown,
"OFFLINE": Offline,
"DISC": Disconnected,
"ISS": ISS,
"IRS": IRS,
"IDLE": Idle,
"FECRcv": FECReceive,
"FECSend": FECSend,
}
func strToState(str string) (State, bool) {
state, ok := stateMap[strings.ToUpper(str)]
return state, ok
}
func debugEnabled() bool {
return os.Getenv("ARDOP_DEBUG") != ""
}