]> code.octet-stream.net Git - m17rt/commitdiff
Make netclient work against mrefd master
authorThomas Karpiniec <tom.karpiniec@outlook.com>
Thu, 5 Jun 2025 09:21:28 +0000 (19:21 +1000)
committerThomas Karpiniec <tom.karpiniec@outlook.com>
Thu, 5 Jun 2025 09:21:28 +0000 (19:21 +1000)
19 files changed:
m17app/src/error.rs
m17app/src/link_setup.rs
m17app/src/reflector.rs
m17app/src/rtlsdr.rs
m17app/src/soundcard.rs
m17app/src/soundmodem.rs
m17app/src/util/out_buffer.rs
m17codec2/src/error.rs
m17codec2/src/rx.rs
m17codec2/src/tx.rs
m17core/src/bits.rs
m17core/src/decode.rs
m17core/src/encode.rs
m17core/src/modem.rs
m17core/src/protocol.rs
m17core/src/reflector/convert.rs
m17core/src/reflector/packet.rs
tools/m17rt-netclient/src/main.rs
tools/m17rt-rxpacket/src/main.rs

index e820eae5101f8a7d7d57e324e108d3691125dd3d..6dbd8c2eed97ff67135b377e3b86cc7631a634cd 100644 (file)
@@ -11,9 +11,7 @@ pub enum M17Error {
     #[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}")]
index b036006b05d7381f0527353e2d1b1de65e208563..2e960a718017f9fd01ded26ad4d4451149dfeadd 100644 (file)
@@ -1,7 +1,7 @@
 use std::fmt::Display;
 
 use m17core::{
-    address::{Address, Callsign, ALPHABET},
+    address::{ALPHABET, Address, Callsign},
     protocol::LsfFrame,
 };
 
index 9b383f72f5cea62a8a534c42a4baaf823b752f00..b5825bb584922ad7b552e2f2bcfe431fbe959133 100644 (file)
@@ -2,9 +2,9 @@ use std::{
     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,
@@ -79,8 +79,9 @@ impl Write for ReflectorClientTnc {
     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];
@@ -196,6 +197,8 @@ fn spawn_runner(
                     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);
@@ -217,7 +220,7 @@ fn run_single_conn(
     };
 
     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();
@@ -263,12 +266,7 @@ fn run_single_conn(
                 }
                 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;
                     }
index 269769b4bd2559452a635c5abb2b43e1234b3ec2..72217cfa13f4fb9a6b5aae384e48f235845cf7f2 100644 (file)
@@ -1,7 +1,7 @@
 use std::{
     io::Read,
     process::{Child, Command, Stdio},
-    sync::{mpsc::SyncSender, Mutex},
+    sync::{Mutex, mpsc::SyncSender},
 };
 
 use crate::{
index 9209de2a09c705642d46158b03476f4ff9a4524e..fb292827acfe764ec891830bcdd676dacc1a8f16 100644 (file)
@@ -1,16 +1,16 @@
 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;
 
index c0cbfbb3121480b2fa0ebf3264f2c0df757e2572..c782d86f85cfacde7a8a02936b3107d8fcdf2e14 100644 (file)
@@ -9,8 +9,8 @@ use std::fmt::Display;
 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;
index c24e0a97d786cd6853748460adf7be83b87c9807..06d8e915708055ad76973cbc4015bfc36e0951c2 100644 (file)
@@ -2,7 +2,7 @@
 
 use std::{
     io::{self, ErrorKind, Read},
-    sync::{mpsc::Receiver, Arc, Mutex},
+    sync::{Arc, Mutex, mpsc::Receiver},
 };
 
 #[derive(Clone)]
index 7fa6583f1f3af20521d5895829a7bfcef30af7ef..b1b3e62892ef988df27ff0c9b7526c304c54f676 100644 (file)
@@ -14,7 +14,9 @@ pub enum M17Codec2Error {
     #[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}'")]
@@ -26,7 +28,9 @@ pub enum M17Codec2Error {
     #[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}'")]
index 5649519c2b50b2acbf5316acee0f90f5e33731df..455ce42966071e489d53d37abe81cc2c25faddbc 100644 (file)
@@ -17,8 +17,8 @@ use std::fs::File;
 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
index a54d864a651ec000750dbab27dbfaa082c5e1c11..d9028fb7f5267ae1a56befa8eb10ec31d747514f 100644 (file)
@@ -1,24 +1,24 @@
 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;
 
index 7b39995770ed1fb00bafbb2591900f58416121b8..4dea6d182ad75d7401d2eb285afa09ebddb7ed40 100644 (file)
@@ -73,7 +73,7 @@ impl<'a> BitsMut<'a> {
     }
 
     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)));
index 3bd8164f322089aed5a03a7a46110ab2f2812005..4bc628869d0fd76df48da34344fdf1a1e881b7cf 100644 (file)
@@ -3,8 +3,8 @@ use crate::{
     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,
 };
index 5e0951e3ff4a3c8c30f8b959b83720fb4adfb060..94d280bb246563e734ff3cc89fc6226c42cd2573 100644 (file)
@@ -3,7 +3,7 @@ use crate::{
     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,
 };
index 43ad5acb3f543279ee7f34b9583121f6c4daf2e8..255678fd97c2b6328962c376e729983a0f360878 100644 (file)
@@ -1,5 +1,5 @@
 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,
index be1eba19202bbef99db388c8f29766125edfbf7b..251fa27fad9b545f6e2be6da945f6f3dc0847d89 100644 (file)
@@ -1,5 +1,5 @@
 use crate::{
-    address::{encode_address, Address},
+    address::{Address, encode_address},
     bits::BitsMut,
 };
 
index fd52df87377908b2b3101f230c607c4c56346dbe..716e68ac3beb2fdfafe8887f55a12e710895d8e3 100644 (file)
@@ -70,7 +70,9 @@ pub struct RfToVoice {
 
 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) {
index 3f746d609ff7b0373aa98564f051c25d80b410db..3dc8378b4ebd384b2252d27b6d96722939138171 100644 (file)
@@ -185,7 +185,7 @@ macro_rules! impl_address {
                 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();
index fbcfb155284981e5f958355c97937a1797fca35d..3204b5bbb0941b492ee0eacb27ffdbc3f0b2c25d 100644 (file)
@@ -34,6 +34,14 @@ fn main() {
                 .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")
@@ -59,11 +67,20 @@ fn main() {
     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);
     }
index a18537e4e87fe02f7fd8290e156fcd144b2ba4f4..adfc444358cd15a33bb7fc51fb8717427565bb6c 100644 (file)
@@ -1,9 +1,9 @@
+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() {