Codebase list golang-github-la5nta-wl2k-go / 4911a91
Update upstream source from tag 'upstream/0.9.2' Update to upstream version '0.9.2' with Debian dir 00afb51a816907e238ef2f15ebce2b5c7c9f6ff1 Federico Grau 2 years ago
8 changed file(s) with 118 addition(s) and 27 deletion(s). Raw diff Collapse all Expand all
00 [![PkgGoDev](https://pkg.go.dev/badge/github.com/la5nta/wl2k-go)](https://pkg.go.dev/github.com/la5nta/wl2k-go)
1 [![Build Status](https://travis-ci.com/la5nta/wl2k-go.svg?branch=master)](https://travis-ci.com/la5nta/wl2k-go)
1 [![Build Status](https://app.travis-ci.com/la5nta/wl2k-go.svg?branch=master)](https://app.travis-ci.com/la5nta/wl2k-go)
22 [![Windows Build Status](https://ci.appveyor.com/api/projects/status/j76on3km4vy5vsq0/branch/master?svg=true)](https://ci.appveyor.com/project/martinhpedersen/wl2k-go)
33 [![Go Report Card](https://goreportcard.com/badge/github.com/la5nta/wl2k-go)](https://goreportcard.com/report/github.com/la5nta/wl2k-go)
44
216216 // The given conn should always be closed after returning from this method.
217217 // If an error occurred, echo it to the remote.
218218 defer func() {
219 defer conn.Close()
219220 switch {
220221 case err == nil:
221222 // Success :-)
232233 // Echo the error to the remote peer and disconnect.
233234 conn.SetDeadline(time.Now().Add(time.Minute))
234235 fmt.Fprintf(conn, "*** %s\r\n", err)
235 conn.Close()
236236 }
237237 }()
238238
4444 ErrConnectTimeout = errors.New("Connect timeout")
4545 ErrChecksumMismatch = errors.New("Control protocol checksum mismatch")
4646 ErrTNCClosed = errors.New("TNC closed")
47 ErrUnsupportedBandwidth = errors.New("Unsupported ARQ bandwidth")
4748 )
4849
4950 // Bandwidth definitions of all supported ARQ bandwidths.
8081 // IsZero returns true if bw is it's zero value.
8182 func (bw Bandwidth) IsZero() bool { return bw.Max == 0 }
8283
84 // BandwidthFromString returns a Bandwidth representation of the given string.
85 //
86 // The string must be a valid ARDOP ARQ bandwidth string (e.g. "2000MAX", "2000FORCED").
87 // The MAX/FORCED suffix may be omitted. Defaults to MAX.
88 func BandwidthFromString(str string) (Bandwidth, error) {
89 // Default to MAX if MAX/FORCED is not given.
90 if strings.HasSuffix(str, "0") {
91 str += "MAX"
92 }
93 for _, bw := range Bandwidths() {
94 if bw.String() == str {
95 return bw, nil
96 }
97 }
98 return Bandwidth{}, ErrUnsupportedBandwidth
99 }
100
101 // Bandwidths returns a list of all ARDOP ARQ bandwidths.
102 func Bandwidths() []Bandwidth {
103 return []Bandwidth{
104 Bandwidth200Max,
105 Bandwidth500Max,
106 Bandwidth1000Max,
107 Bandwidth2000Max,
108 Bandwidth200Forced,
109 Bandwidth500Forced,
110 Bandwidth1000Forced,
111 Bandwidth2000Forced,
112 }
113 }
114
83115 var stateMap = map[string]State{
84116 "": Unknown,
85117 "OFFLINE": Offline,
137137 case cmdAbort, cmdDisconnect, cmdClose, cmdDisconnected, cmdCRCFault, cmdPending, cmdCancelPending, cmdSendID:
138138
139139 // (echo-back only)
140 case cmdInitialize, cmdARQCall, cmdARQBW, cmdProtocolMode:
140 case cmdInitialize, cmdARQCall, cmdProtocolMode:
141141
142142 // State
143143 case cmdNewState, cmdState:
145145
146146 // string
147147 case cmdFault, cmdMyCall, cmdGridSquare, cmdCapture,
148 cmdPlayback, cmdVersion, cmdTarget, cmdStatus:
148 cmdPlayback, cmdVersion, cmdTarget, cmdStatus, cmdARQBW:
149149 msg.value = parts[1]
150150
151151 // []string (space separated)
1010
1111 func TestParse(t *testing.T) {
1212 tests := map[string]ctrlMsg{
13 "NEWSTATE DISC": ctrlMsg{cmdNewState, Disconnected},
14 "PTT True": ctrlMsg{cmdPTT, true},
15 "PTT False": ctrlMsg{cmdPTT, false},
16 "PTT trUE": ctrlMsg{cmdPTT, true},
17 "CODEC True": ctrlMsg{cmdCodec, true},
18 "foobar baz": ctrlMsg{command("FOOBAR"), nil},
19 "DISCONNECTED": ctrlMsg{cmdDisconnected, nil},
20 "FAULT 5/Error in the application.": ctrlMsg{cmdFault, "5/Error in the application."},
21 "BUFFER 300": ctrlMsg{cmdBuffer, 300},
22 "MYCALL LA5NTA": ctrlMsg{cmdMyCall, "LA5NTA"},
23 "GRIDSQUARE JP20QH": ctrlMsg{cmdGridSquare, "JP20QH"},
24 "MYAUX LA5NTA,LE3OF": ctrlMsg{cmdMyAux, []string{"LA5NTA", "LE3OF"}},
25 "MYAUX LA5NTA, LE3OF": ctrlMsg{cmdMyAux, []string{"LA5NTA", "LE3OF"}},
26 "VERSION 1.4.7.0": ctrlMsg{cmdVersion, "1.4.7.0"},
27 "FREQUENCY 14096400": ctrlMsg{cmdFrequency, 14096400},
13 "NEWSTATE DISC": {cmdNewState, Disconnected},
14 "PTT True": {cmdPTT, true},
15 "PTT False": {cmdPTT, false},
16 "PTT trUE": {cmdPTT, true},
17 "CODEC True": {cmdCodec, true},
18 "foobar baz": {command("FOOBAR"), nil},
19 "DISCONNECTED": {cmdDisconnected, nil},
20 "FAULT 5/Error in the application.": {cmdFault, "5/Error in the application."},
21 "BUFFER 300": {cmdBuffer, 300},
22 "MYCALL LA5NTA": {cmdMyCall, "LA5NTA"},
23 "GRIDSQUARE JP20QH": {cmdGridSquare, "JP20QH"},
24 "MYAUX LA5NTA,LE3OF": {cmdMyAux, []string{"LA5NTA", "LE3OF"}},
25 "MYAUX LA5NTA, LE3OF": {cmdMyAux, []string{"LA5NTA", "LE3OF"}},
26 "VERSION 1.4.7.0": {cmdVersion, "1.4.7.0"},
27 "FREQUENCY 14096400": {cmdFrequency, 14096400},
28 "ARQBW 200MAX": {cmdARQBW, "200MAX"},
2829 }
2930 for input, expected := range tests {
3031 got := parseCtrlMsg(input)
2323 eofChan chan struct{}
2424 ctrlIn broadcaster
2525 isTCP bool
26 onClose []func() error
2627
2728 remoteAddr Addr
2829 localAddr Addr
3839 nWritten int
3940 }
4041
41 //TODO: implement
42 // TODO: implement
4243 func (conn *tncConn) SetDeadline(t time.Time) error { return nil }
4344 func (conn *tncConn) SetReadDeadline(t time.Time) error { return nil }
4445 func (conn *tncConn) SetWriteDeadline(t time.Time) error { return nil }
5758 }
5859
5960 if len(data) > len(p) {
60 panic("too large") //TODO: Handle
61 panic("too large") // TODO: Handle
6162 }
6263
6364 for i, b := range data {
7172 conn.dataLock.Lock()
7273 defer conn.dataLock.Unlock()
7374
74 //TODO: Consider implementing chunking
75 // TODO: Consider implementing chunking
7576 if len(p) > 65535 { // uint16 (length bytes) max
7677 p = p[:65535]
7778 }
142143
143144 func (conn *tncConn) signalClosed() { close(conn.eofChan) }
144145
145 const flushAndCloseTimeout = 30 * time.Second //TODO: Remove when time is right (see Close).
146 const flushAndCloseTimeout = 30 * time.Second // TODO: Remove when time is right (see Close).
146147
147148 // Close closes the current connection.
148149 //
151152 if conn == nil {
152153 return nil
153154 }
155
156 defer func() {
157 for _, fn := range conn.onClose {
158 err := fn()
159 if err != nil && debugEnabled() {
160 log.Printf("onClose func failed: %v", err)
161 }
162 }
163 }()
154164
155165 // Flush: (THIS WILL PROBABLY BE REMOVED WHEN ARDOP MATURES)
156166 // We have to flush, because ardop will disconnect without waiting for the last
1010 "github.com/la5nta/wl2k-go/transport"
1111 )
1212
13 // DialURL dials ardop:// URLs
13 // DialURL dials ardop:// URLs.
14 //
15 // Parameter bw can be used to set the ARQ bandwidth for this connection. See DialBandwidth for details.
1416 func (tnc *TNC) DialURL(url *transport.URL) (net.Conn, error) {
1517 if url.Scheme != "ardop" {
1618 return nil, transport.ErrUnsupportedScheme
1719 }
18
19 return tnc.Dial(url.Target)
20 bwStr := url.Params.Get("bw")
21 if bwStr == "" {
22 return tnc.Dial(url.Target)
23 }
24 bw, err := BandwidthFromString(bwStr)
25 if err != nil {
26 return nil, err
27 }
28 return tnc.DialBandwidth(url.Target, bw)
2029 }
2130
31 // Dial dials a ARQ connection.
2232 func (tnc *TNC) Dial(targetcall string) (net.Conn, error) {
33 return tnc.DialBandwidth(targetcall, Bandwidth{})
34 }
35
36 // DialBandwidth dials a ARQ connection after setting the given ARQ bandwidth temporarily.
37 //
38 // The ARQ bandwidth setting is reverted on any Dial error and when calling conn.Close().
39 func (tnc *TNC) DialBandwidth(targetcall string, bw Bandwidth) (net.Conn, error) {
2340 if tnc.closed {
2441 return nil, ErrTNCClosed
2542 }
2643
44 var defers []func() error
45 if !bw.IsZero() {
46 currentBw, err := tnc.ARQBandwidth()
47 if err != nil {
48 return nil, err
49 }
50 if err := tnc.SetARQBandwidth(bw); err != nil {
51 return nil, err
52 }
53 defers = append(defers, func() error { return tnc.SetARQBandwidth(currentBw) })
54 }
55
2756 if err := tnc.arqCall(targetcall, 10); err != nil {
57 for _, fn := range defers {
58 _ = fn()
59 }
2860 return nil, err
2961 }
3062
3163 mycall, err := tnc.MyCall()
3264 if err != nil {
65 for _, fn := range defers {
66 _ = fn()
67 }
3368 return nil, fmt.Errorf("Error when getting mycall: %s", err)
3469 }
3570
4277 dataIn: tnc.dataIn,
4378 eofChan: make(chan struct{}),
4479 isTCP: tnc.isTCP,
80 onClose: defers,
4581 }
4682
4783 return tnc.data, nil
301301 }
302302
303303 if err != nil {
304 panic(err) //FIXME
304 panic(err) // FIXME
305305 }
306306 }
307307 }
404404 // Sets the ARQ bandwidth
405405 func (tnc *TNC) SetARQBandwidth(bw Bandwidth) error {
406406 return tnc.set(cmdARQBW, bw)
407 }
408
409 func (tnc *TNC) ARQBandwidth() (Bandwidth, error) {
410 str, err := tnc.getString(cmdARQBW)
411 if err != nil {
412 return Bandwidth{}, err
413 }
414 bw, err := BandwidthFromString(str)
415 if err != nil {
416 return Bandwidth{}, fmt.Errorf("invalid ARQBW response: %w", err)
417 }
418 return bw, nil
407419 }
408420
409421 // Sets the ARQ timeout