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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
//! An Async Rust interface to the ARDOP TNC
//!
//! [Documentation](https://docs.rs/ardop_interface) |
//! [Crate](https://crates.io/crates/ardop_interface) |
//! [Git](https://github.com/cbs228/ardop_interface)
//!
//! # Introduction
//!
//! `ardop_interface` integrates with the Amateur Radio Digital
//! Open Protocol ([ARDOP](https://ardop.groups.io/g/main)) soundcard
//! modem softare. The ARDOP modem is intended to provide reliable,
//! low-speed connectivity over High Frequency (HF) radio links.
//!
//! *This crate is not ARDOP.* This crate is only an interface. With
//! this interface, and separate ARDOP modem software, you can build
//! full-featured Rust applications that communicate over the radio.
//!
//! # Minimal Example
//!
//! ```no_run
//! #![feature(async_await)]
//! use std::net::SocketAddr;
//! use futures::prelude::*;
//!
//! use ardop_interface::tnc::*;
//!
//! #[runtime::main]
//! async fn main() {
//!    let addr = "127.0.0.1:8515".parse().unwrap();
//!    let mut tnc = ArdopTnc::new(&addr, "MYC4LL")
//!        .await
//!        .unwrap();
//!    let mut conn = tnc.connect("T4GET", 500, false, 3)
//!        .await
//!        .expect("TNC failure")
//!        .expect("Connection failed");
//!    conn.write_all(b"Hello, world!\n").await.unwrap();
//!    conn.close().await;
//! }
//! ```
//!
//! See the
//! [`examples/`](https://github.com/cbs228/ardop_interface/tree/master/examples)
//! directory in the source code repository for a complete client
//! and server. The examples also demonstrate the `async` `runtime` crate,
//! argument parsing, and logging.
//!
//! # The ARDOP Modem
//!
//! Like most amateur radio modems, ARDOP is designed to interface
//! with analog, single-sideband (SSB) transceivers via a sound
//! card interface. A computer—which may be a simple, single-board
//! computer—turns data into sound, and back again.
//!
//! ARDOP is designed to:
//!
//! * Automatically retry failed transmissions. This mode of
//!   operation is called *automatic repeat request* (ARQ),
//!   and it helps ensure that data reaches its final destination.
//!
//! * Use the fastest available mode for the signal-to-noise ratio
//!   and band conditions
//!
//! * Support unattended, automatic station operation
//!
//! * Perform well on the high frequency (HF) bands
//!
//! Best of all, ARDOP has an open development model. Full protocol
//! specifications are available, and open-source implementations of
//! the modem exist.
//!
//! ARDOP is intended for use by licensed radio amateurs. If you'd
//! like to get started with the hobby, you should find a club,
//! "hamfest," or "hamvention" near you!
//!
//! # The Rust Interface
//!
//! The ARDOP software has a standardized "terminal node controller"
//! (TNC) interface for clients to use. To use the TNC, clients must
//! make two simultaneous TCP connections and perform a great deal
//! of serialization and de-serialization. This crate handles many
//! of these details for you.
//!
//! This crate exposes an `async` API that many rustaceans will
//! find familiar: socket programming. The
//! [`ArqStream`](arq/index.html) object is designed
//! to mimic an async `TcpStream`. Once a connection is made,
//! data is exchanged with asynchronous reads from, and writes to,
//! the `ArqStream` object.
//!
//! The `async` API allows ARDOP to coexist with native TCP sockets,
//! GUIs, and other I/O processes while maintaining a small system
//! resource footprint.
//!
//! # Development Status
//!
//! This crate's API will not stabilize until the stable release
//! of
//! * the [futures-preview](https://docs.rs/futures-preview/) crate; and
//! * the [async-await](https://areweasyncyet.rs/) Rust language feature.
//!
//! For now, it is necessary to use a `nightly` Rust toolchain.
//!
//! This crate has been tested against rust `1.37.0-nightly` built
//! on `2019-06-23`. Earlier builds may not function correctly.
//!
//! # Prerequisites
//!
//! First, ensure that a nightly Rust is installed and available on
//! your platform.
//!
//! ```bash
//! rustup toolchain install nightly
//! rustup default nightly
//! ```
//!
//! Next, obtain a compatible implementation of ARDOP. You must use
//! ARDOP software which implements protocol **version one**.
//! The ARDOP v2 specification has been withdrawn by its authors, and
//! version three is presently in development. The TNC interface on
//! which this crate depends can change during major releases.
//!
//! These instructions assume the use of John Wiseman's `ardopc`, version 1.
//! Other implementations will probably work, but this crate has not
//! been tested against them. You may be able to obtain this software at
//! <http://www.cantab.net/users/john.wiseman/Downloads/Beta/TeensyProjects.zip>
//! or from the ARDOP [forums](https://ardop.groups.io/g/users/topics).
//!
//! You will need your system's C/C++ compiler in order to build `ardopc`.
//! Debian-based distributions can install these with:
//!
//! ```bash
//! sudo apt-get install build-essential
//! ```
//!
//! Unpack the archive, `cd` into the `ARDOPC` subdirectory, and
//! run `make` to build the software. There is also a Visual Studio
//! project for Windows users. Alternatively, binary builds may be
//! available in
//! <http://www.cantab.net/users/john.wiseman/Downloads/Beta/>.
//!
//! You should now be able to invoke ARDOP as
//!
//! ```bash
//! ./ardopc PORT INDEV OUTDEV
//! ```
//!
//! where
//! * `PORT` is the desired TCP control port (typically `8515`)
//! * `INDEV` is the ALSA device name for your "`line in`"
//!   soundcard port. If your system has pulseaudio, you may use
//!   it with the `pulse` device.
//! * `OUTDEV` is the ALSA device name for your "`line out`"
//!   soundcard port. If your system has pulseaudio, you may use
//!   it with the `pulse` device.
//!
//! # Running the Examples
//!
//! The examples are not published to `crates.io.` You will need
//! to clone our source repository instead:
//!
//! ```bash
//! git clone https://github.com/cbs228/ardop_interface.git
//! ```
//!
//! To conduct a local test of ARDOP, you must run two instances
//! of the ARDOP modem. To make an acoustic channel between the
//! two the modems, place your microphone in close proximity to
//! your speakers. Alternatively, on linux, you may also use the
//! PulseAudio null sink:
//!
//! ```bash
//! pacmd load-module module-null-sink sink_name=Virtual1
//! pacmd set-default-sink Virtual1
//! pacmd set-default-source Virtual1.monitor
//! ```
//!
//! Start two instances of ardopc
//!
//! ```bash
//! ./ardopc 8515 pulse pulse &
//! ./ardopc 8520 pulse pulse &
//! ```
//!
//! Build and run the `echoserver` package with
//!
//! ```bash
//! cargo run --package echoserver -- localhost:8515 MYCALL-S 200
//! ```
//!
//! Replace `MYCALL` with your callsign. The `-S` is a
//! Service Set Identifier (SSID), which is an arbitrary
//! single-character extension to your callsign.
//!
//! Now run the `echoclient` with
//!
//! ```bash
//! cargo run --package echoclient -- localhost:8520 MYCALL-C MYCALL-S 200
//! ```
//!
//! The `echoclient` will send a number of pre-programmed
//! text stanzas to the `echoserver`, which will parrot them
//! back. Both the client and server will print their progress
//! to stderr. The demo succeeds if the client prints
//!
//! ```txt
//! Echo server echoed all stanzas correctly.
//! ```
//!
//! You can also use the `echoserver` interactively via a
//! line-oriented chat program, like `ARIM`.
//!
//! When you are finished, remove the null sink if you are
//! using it.
//!
//! ```bash
//! pacmd unload-module module-null-sink
//! ```
//!
//! # Unsupported ARDOP Features
//!
//! At present, this crate only supports the ARDOP `ARQ`
//! connection-oriented protocol, which is TCP-like. ARDOP also
//! has a connectionless `FEC` protocol, which is UDP-like.
//! `ardop_interface` does not currently support FEC mode.
//!
//! The following other features are currently not implemented
//! by this crate.
//!
//! * **Busy channel detection**: This crate relies on the
//!   ARDOP TNC to perform busy channel detection. Support for
//!   this functionality varies across ARDOP implementations.
//!
//! * **Rig control**: No type of rig control is presently
//!   integrated. This crate cannot provide the following
//!   functionality, at present.
//!
//!   * **Tuning**: `ardop_interface` knows nothing about your rig
//!     and cannot adjust its frequency or mode.
//!
//!   * **Keying**: This crate does not key your radio's PTT.
//!     The ARDOP TNC may be able to do this for you. `ardopc` can
//!     key transmitters over a serial connection.
//!
//!   * **Scanning**: The ARDOP frequency agility / scanning functions
//!     in `LISTEN` mode are not supported
//!
//! # Next Steps
//!
//! What sorts of protocols would you like to see on the air?
//! With a reliable, TCP-like link between stations, the
//! ionosphere is the limit!
//!
//! # Further Reading
//!
//! * [`tnc`](tnc/index.html): Main TNC command and control via the
//!   `ArdopTnc`
//! * [`arq`](arq/index.html): Reliable ARQ connections with
//!   `ArqStream`

#![feature(async_await)]
#![recursion_limit = "128"]
#[allow(unused_imports)]
#[macro_use]
extern crate custom_derive;
#[macro_use]
extern crate enum_derive;
#[allow(unused_imports)]
#[macro_use]
extern crate nom;
extern crate bytes;
#[macro_use]
extern crate futures;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate num;
extern crate regex;
extern crate runtime;

pub mod arq;
pub mod framer;
pub mod tnc;

mod framing;
mod protocol;
mod tncio;