#[error("given callsign is {0} characters long; maximum is 9")]
CallsignTooLong(usize),
- #[error(
- "provided packet payload is too large: provided {provided} bytes, capacity {capacity}"
- )]
+ #[error("provided packet payload is too large: provided {provided} bytes, capacity {capacity}")]
PacketTooLarge { provided: usize, capacity: usize },
#[error("provided path to RRC file could not be opened: {0}")]
use std::fmt::Display;
use m17core::{
- address::{Address, Callsign, ALPHABET},
+ address::{ALPHABET, Address, Callsign},
protocol::LsfFrame,
};
io::{self, Read, Write},
net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs, UdpSocket},
sync::{
+ Arc, Mutex,
atomic::{AtomicBool, Ordering},
mpsc::{self, Receiver, Sender},
- Arc, Mutex,
},
thread,
time::Duration,
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
let mut kiss = self.kiss_buffer.lock().unwrap();
let rem = kiss.buf_remaining();
- let sz = buf.len().max(rem.len());
+ let sz = buf.len().min(rem.len());
rem[0..sz].copy_from_slice(&buf[0..sz]);
+ kiss.did_write(sz);
if let Some(frame) = kiss.next_frame() {
if Ok(KissCommand::DataFrame) == frame.command() && frame.port() == Ok(PORT_STREAM) {
let mut payload = [0u8; 30];
config.clone(),
status.clone(),
);
+ // Cool off a bit if connect rejected, etc.
+ thread::sleep(Duration::from_secs(10));
}
}
status.lock().unwrap().status_changed(TncStatus::Closed);
};
let mut connect = Connect::new();
- connect.set_address(config.local_callsign.address().to_owned());
+ connect.set_address(config.local_callsign.address());
connect.set_module(config.module);
let _ = socket.send_to(connect.as_bytes(), dest);
let mut converter = VoiceToRf::new();
}
ServerMessage::Ping(_ping) => {
let mut pong = Pong::new();
- pong.set_address(
- M17Address::from_callsign("VK7XT")
- .unwrap()
- .address()
- .clone(),
- );
+ pong.set_address(config.local_callsign.address());
if socket.send_to(pong.as_bytes(), dest).is_err() {
break;
}
use std::{
io::Read,
process::{Child, Command, Stdio},
- sync::{mpsc::SyncSender, Mutex},
+ sync::{Mutex, mpsc::SyncSender},
};
use crate::{
use std::{
borrow::Borrow,
sync::{
- mpsc::{sync_channel, Receiver, SyncSender},
Arc, RwLock,
+ mpsc::{Receiver, SyncSender, sync_channel},
},
time::{Duration, Instant},
};
use cpal::{
- traits::{DeviceTrait, HostTrait, StreamTrait},
BuildStreamError, DevicesError, PlayStreamError, SampleFormat, SampleRate, Stream, StreamError,
SupportedStreamConfigRange, SupportedStreamConfigsError,
+ traits::{DeviceTrait, HostTrait, StreamTrait},
};
use thiserror::Error;
use std::fs::File;
use std::io::{self, Read, Write};
use std::path::PathBuf;
-use std::sync::mpsc::{channel, sync_channel, Receiver, Sender, SyncSender, TryRecvError};
use std::sync::RwLock;
+use std::sync::mpsc::{Receiver, Sender, SyncSender, TryRecvError, channel, sync_channel};
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use thiserror::Error;
use std::{
io::{self, ErrorKind, Read},
- sync::{mpsc::Receiver, Arc, Mutex},
+ sync::{Arc, Mutex, mpsc::Receiver},
};
#[derive(Clone)]
#[error("selected card '{0}' failed to list available output configs: '{1}'")]
OutputConfigsUnavailable(String, #[source] cpal::SupportedStreamConfigsError),
- #[error("selected card '{0}' did not offer a compatible output config type, either due to hardware limitations or because it is currently in use")]
+ #[error(
+ "selected card '{0}' did not offer a compatible output config type, either due to hardware limitations or because it is currently in use"
+ )]
SupportedOutputUnavailable(String),
#[error("selected card '{0}' was unable to build an output stream: '{1}'")]
#[error("selected card '{0}' failed to list available input configs: '{1}'")]
InputConfigsUnavailable(String, #[source] cpal::SupportedStreamConfigsError),
- #[error("selected card '{0}' did not offer a compatible input config type, either due to hardware limitations or because it is currently in use")]
+ #[error(
+ "selected card '{0}' did not offer a compatible input config type, either due to hardware limitations or because it is currently in use"
+ )]
SupportedInputUnavailable(String),
#[error("selected card '{0}' was unable to build an input stream: '{1}'")]
use std::io::Write;
use std::path::Path;
use std::sync::{
- mpsc::{channel, Receiver, Sender},
Arc, Mutex,
+ mpsc::{Receiver, Sender, channel},
};
/// Write one or more 8-byte chunks of 3200-bit Codec2 to a raw S16LE file
use codec2::{Codec2, Codec2Mode};
+use cpal::SampleFormat;
+use cpal::SampleRate;
use cpal::traits::DeviceTrait;
use cpal::traits::HostTrait;
use cpal::traits::StreamTrait;
-use cpal::SampleFormat;
-use cpal::SampleRate;
use log::debug;
+use m17app::StreamFrame;
use m17app::adapter::StreamAdapter;
use m17app::app::TxHandle;
use m17app::error::AdapterError;
use m17app::link_setup::LinkSetup;
use m17app::link_setup::M17Address;
-use m17app::StreamFrame;
use rubato::Resampler;
use rubato::SincFixedOut;
use rubato::SincInterpolationParameters;
use std::path::PathBuf;
-use std::sync::mpsc;
-use std::sync::mpsc::channel;
use std::sync::Arc;
use std::sync::Mutex;
+use std::sync::mpsc;
+use std::sync::mpsc::channel;
use std::time::Duration;
use std::time::Instant;
}
pub(crate) fn set_bit(&mut self, idx: usize, value: u8) {
- let slice = &mut self.0 .0;
+ let slice = &mut self.0.0;
let existing = slice[idx / 8];
if value == 0 {
slice[idx / 8] = existing & !(1 << (7 - (idx % 8)));
fec::{self, p_1, p_2, p_3},
interleave::interleave,
protocol::{
- LsfFrame, PacketFrame, PacketFrameCounter, StreamFrame, BERT_SYNC, END_OF_TRANSMISSION,
- LSF_SYNC, PACKET_SYNC, PREAMBLE, STREAM_SYNC,
+ BERT_SYNC, END_OF_TRANSMISSION, LSF_SYNC, LsfFrame, PACKET_SYNC, PREAMBLE, PacketFrame,
+ PacketFrameCounter, STREAM_SYNC, StreamFrame,
},
random::random_xor,
};
fec::{self, p_1, p_2, p_3},
interleave::interleave,
protocol::{
- LsfFrame, PacketFrame, PacketFrameCounter, StreamFrame, LSF_SYNC, PACKET_SYNC, STREAM_SYNC,
+ LSF_SYNC, LsfFrame, PACKET_SYNC, PacketFrame, PacketFrameCounter, STREAM_SYNC, StreamFrame,
},
random::random_xor,
};
use crate::decode::{
- parse_lsf, parse_packet, parse_stream, sync_burst_correlation, SyncBurst, SYNC_THRESHOLD,
+ SYNC_THRESHOLD, SyncBurst, parse_lsf, parse_packet, parse_stream, sync_burst_correlation,
};
use crate::encode::{
encode_lsf, encode_packet, encode_stream, generate_end_of_transmission, generate_preamble,
use crate::{
- address::{encode_address, Address},
+ address::{Address, encode_address},
bits::BitsMut,
};
impl RfToVoice {
pub fn new(lsf: LsfFrame) -> Self {
- Self { lsf, stream_id: 0 }
+ // no_std "random"
+ let stream_id = &lsf as *const LsfFrame as u16;
+ Self { lsf, stream_id }
}
pub fn process_lsf(&mut self, lsf: LsfFrame) {
crate::address::decode_address(self.0[$from..($from + 6)].try_into().unwrap())
}
- pub fn set_address(&mut self, address: Address) {
+ pub fn set_address(&mut self, address: &Address) {
let encoded = crate::address::encode_address(&address);
self.0[$from..($from + 6)].copy_from_slice(&encoded);
self.recalculate_crc();
.required(true)
.help("Your callsign for reflector registration and transmissions"),
)
+ .arg(
+ Arg::new("reflector")
+ .long("reflector")
+ .short('r')
+ .value_parser(valid_callsign)
+ .required(true)
+ .help("Reflector designator/callsign, often starting with 'M17-'"),
+ )
.arg(
Arg::new("module")
.long("module")
let hostname = args.get_one::<String>("hostname").unwrap();
let port = args.get_one::<u16>("port").unwrap();
let callsign = args.get_one::<M17Address>("callsign").unwrap();
+ let reflector = args.get_one::<M17Address>("reflector").unwrap();
let module = args.get_one::<char>("module").unwrap();
let input = args.get_one::<String>("input");
let output = args.get_one::<String>("output");
- let mut tx = Codec2TxAdapter::new(callsign.clone(), M17Address::new_broadcast());
+ let ref_with_mod = format!("{} {}", reflector, module);
+ let Ok(reflector) = M17Address::from_callsign(&ref_with_mod) else {
+ println!(
+ "Unable to create valid destination address for reflector + callsign '{ref_with_mod}'"
+ );
+ std::process::exit(1);
+ };
+
+ let mut tx = Codec2TxAdapter::new(callsign.clone(), reflector);
if let Some(input) = input {
tx.set_input_card(input);
}
+use m17app::PacketType;
use m17app::adapter::PacketAdapter;
use m17app::app::M17App;
use m17app::link_setup::LinkSetup;
use m17app::soundcard::Soundcard;
use m17app::soundmodem::{NullErrorHandler, NullOutputSink, NullPtt, Soundmodem};
-use m17app::PacketType;
use std::sync::Arc;
fn main() {