ush 0.1.0

Ultrasonic Shell - communicate between devices using ultrasonic sound waves
Documentation
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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# Communication Protocol

## Overview

The `ush` protocol implements a reliable data link layer protocol optimized for acoustic transmission. It provides message framing, error detection, sequencing, and basic flow control over the unreliable acoustic channel.

## Protocol Stack

```
┌─────────────────────────────────────┐
│        Application Messages         │  Text, Files, Commands
├─────────────────────────────────────┤
│         Message Protocol            │  JSON Serialization
├─────────────────────────────────────┤
│          Frame Protocol             │  Framing, CRC, Sequencing
├─────────────────────────────────────┤
│         FSK Modulation              │  Digital → Acoustic
├─────────────────────────────────────┤
│         Audio Channel               │  Speakers ↔ Microphones
└─────────────────────────────────────┘
```

## Frame Structure

### Frame Format

Each transmitted frame follows this structure:

```
┌─────────────┬─────────────┬─────────────┬─────────────┬─────────────┐
│   Preamble  │    Start    │   Length    │   Payload   │     End     │
│   8 bytes   │   2 bytes   │   2 bytes   │  Variable   │   2 bytes   │
└─────────────┴─────────────┴─────────────┴─────────────┴─────────────┘
```

### Field Descriptions

1. **Preamble (8 bytes)**: `0xAAAAAAAAAAAAAAAA`
   - Alternating pattern for receiver synchronization
   - Allows clock recovery and signal detection
   - Double preamble (2×4 bytes) for robust detection

2. **Start Delimiter (2 bytes)**: `0x7E7E`
   - Unique pattern indicating frame start
   - Based on HDLC flag sequence¹
   - Repeated for reliability

3. **Length Field (2 bytes)**: Big-endian message length
   - Maximum payload: 1024 bytes
   - Includes serialized message data
   - Used for frame boundary detection

4. **Payload (Variable)**: JSON-serialized message
   - Contains application data
   - Includes CRC checksum within message
   - Structured as `Message` object

5. **End Delimiter (2 bytes)**: `0x7E7E`
   - Frame termination marker
   - Enables frame validation
   - Same pattern as start for simplicity

### Message Structure

The payload contains a JSON-serialized `Message` object:

```rust
#[derive(Serialize, Deserialize)]
pub struct Message {
    pub header: MessageHeader,
    pub payload: Vec<u8>,
    pub checksum: u32,
}

#[derive(Serialize, Deserialize)]  
pub struct MessageHeader {
    pub version: u8,           // Protocol version (currently 1)
    pub message_type: MessageType,
    pub sequence_number: u32,  // For ordering and deduplication
    pub timestamp: u64,        // Unix timestamp in seconds
    pub payload_length: u16,   // Length of payload field
}
```

### Message Types

```rust
#[derive(Serialize, Deserialize)]
pub enum MessageType {
    Text,     // Human-readable text messages
    File,     // File transfer chunks
    Ack,      // Acknowledgment messages
    Ping,     // Connectivity testing
}
```

## Error Detection

### CRC-32 Implementation

The protocol uses CRC-32 with the ISO HDLC polynomial² for error detection:

**Polynomial**: `x³² + x²⁶ + x²³ + x²² + x¹⁶ + x¹² + x¹¹ + x¹⁰ + x⁸ + x⁷ + x⁵ + x⁴ + x² + x + 1`

**Implementation**:
```rust
use crc::{Crc, CRC_32_ISO_HDLC};

fn calculate_checksum(header: &MessageHeader, payload: &[u8]) -> UshResult<u32> {
    let crc = Crc::<u32>::new(&CRC_32_ISO_HDLC);
    
    // Serialize header to bytes for checksum calculation
    let header_bytes = serde_json::to_vec(header)?;
    
    let mut digest = crc.digest();
    digest.update(&header_bytes);
    digest.update(payload);
    
    Ok(digest.finalize())
}
```

### Error Detection Capability

CRC-32 provides strong error detection:
- **Undetected error probability**: ~2³² ≈ 1 in 4.3 billion
- **Burst error detection**: Up to 32 consecutive bit errors
- **Random error detection**: Any odd number of bit errors³

### Checksum Verification Process

1. **Sender**:
   ```rust
   let checksum = calculate_checksum(&header, &payload)?;
   let message = Message { header, payload, checksum };
   ```

2. **Receiver**:
   ```rust
   fn verify_checksum(&self) -> UshResult<bool> {
       let calculated = Self::calculate_checksum(&self.header, &self.payload)?;
       Ok(calculated == self.checksum)
   }
   ```

3. **Error Handling**:
   - Invalid checksums trigger frame rejection
   - Corrupted frames are logged for debugging
   - Automatic retry logic in higher layers

## Frame Synchronization

### Decoder State Machine

The protocol decoder implements a finite state machine for robust frame processing⁴:

```rust
#[derive(Debug, PartialEq)]
enum DecoderState {
    WaitingForPreamble,    // Scanning for preamble pattern
    WaitingForStart,       // Looking for start delimiter
    ReadingLength,         // Reading 2-byte length field  
    ReadingMessage,        // Reading variable-length payload
    WaitingForEnd,         // Expecting end delimiter
}
```

### State Transitions

```
┌─────────────────────┐
│ WaitingForPreamble  │────┐
└─────────────────────┘    │ Preamble found
           ▲               ▼
           │          ┌──────────────┐
    Reset  │          │WaitingForStart│
           │          └──────────────┘
           │               │ Start delimiter found
           │               ▼
           │          ┌──────────────┐
           │          │ ReadingLength│
           │          └──────────────┘
           │               │ Length read
           │               ▼
           │          ┌──────────────┐
    Error  │          │ReadingMessage│
           │          └──────────────┘
           │               │ Message complete
           │               ▼
           │          ┌──────────────┐
           └──────────│ WaitingForEnd│
                      └──────────────┘
                           │ End delimiter found
                      [Frame Complete]
```

### Preamble Detection

The preamble detection algorithm uses pattern matching:

```rust
fn find_preamble(&self) -> Option<usize> {
    let double_preamble = [PREAMBLE, PREAMBLE].concat(); // 0xAAAA...
    
    if self.buffer.len() < double_preamble.len() {
        return None;
    }
    
    for i in 0..=self.buffer.len() - double_preamble.len() {
        if &self.buffer[i..i + double_preamble.len()] == double_preamble {
            return Some(i);
        }
    }
    
    None
}
```

### Frame Boundary Detection

The system uses multiple mechanisms for frame boundary detection:

1. **Length Field Validation**: Prevents buffer overflows
2. **Maximum Frame Size**: 1024 bytes + overhead
3. **Timeout Mechanism**: Prevents indefinite blocking
4. **Pattern Validation**: Start/end delimiters must match

## Sequencing and Flow Control

### Sequence Numbers

Messages include monotonically increasing sequence numbers:
- **32-bit counter**: Wraps at 2³² - 1
- **Per-session uniqueness**: Reset for each communication session
- **Gap detection**: Missing sequences indicate lost frames

### Acknowledgment Protocol

Basic stop-and-wait ARQ (Automatic Repeat reQuest)⁵:

```rust
pub fn new_ack(sequence_number: u32) -> UshResult<Self> {
    let header = MessageHeader {
        version: PROTOCOL_VERSION,
        message_type: MessageType::Ack,
        sequence_number,
        timestamp: current_timestamp(),
        payload_length: 0,
    };
    
    Ok(Self {
        header,
        payload: Vec::new(),
        checksum: Self::calculate_checksum(&header, &[])?,
    })
}
```

### Timeout and Retransmission

While not fully implemented in the current version, the protocol supports:
- **Configurable timeouts**: Based on channel characteristics
- **Exponential backoff**: Reduces network congestion
- **Maximum retry count**: Prevents infinite loops

## Serialization

### JSON Message Format

Messages are serialized using serde_json for human readability and debugging:

**Example Text Message**:
```json
{
  "header": {
    "version": 1,
    "message_type": "Text",
    "sequence_number": 42,
    "timestamp": 1703097600,
    "payload_length": 13
  },
  "payload": [72, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33],
  "checksum": 3735928559
}
```

### Serialization Trade-offs

**Advantages**:
- Human-readable for debugging
- Self-describing format
- Language interoperability
- Schema evolution support

**Disadvantages**:
- Higher overhead than binary protocols
- JSON parsing complexity
- Larger frame sizes

**Alternative Considered**: MessagePack⁶ or Protocol Buffers⁷ for binary efficiency

## Protocol Extensions

### File Transfer Protocol

Large files are segmented into chunks:

```rust
let message = format!("FILE:{}:{}:{}", 
                     filename,
                     sequence_number,
                     base64::encode(chunk));
```

**File Transfer State**:
- **Sender**: Tracks bytes sent, chunk sequence
- **Receiver**: Reassembles chunks, detects completion
- **Error Recovery**: Retransmit missing chunks

### Chat Protocol Enhancement

For interactive communication:
- **User identification**: Username in message headers
- **Presence indication**: Periodic ping messages
- **Message threading**: Reply-to sequence numbers

## Performance Optimization

### Buffer Management

The decoder uses bounded buffers to prevent memory exhaustion:

```rust
// Keep buffer size reasonable
if self.buffer.len() > 10000 {
    let keep_size = 5000;
    self.buffer.drain(..self.buffer.len() - keep_size);
    self.state = DecoderState::WaitingForPreamble;
}
```

### Partial Frame Processing

The decoder processes data incrementally:
- **Stream processing**: No need to buffer complete frames
- **Early validation**: Reject invalid frames quickly  
- **Memory efficiency**: Bounded buffer sizes

## Security Considerations

### Current Limitations

The protocol currently lacks security features:
- **No encryption**: Messages transmitted in plaintext
- **No authentication**: No sender verification
- **No integrity beyond CRC**: CRC is error detection, not cryptographic

### Future Security Enhancements

1. **Symmetric Encryption**: AES-GCM for confidentiality
2. **Pre-shared Keys**: Simple key distribution
3. **Message Authentication**: HMAC for integrity
4. **Replay Protection**: Sequence number validation

```rust
// Potential security-enhanced message structure
pub struct SecureMessage {
    pub header: MessageHeader,
    pub encrypted_payload: Vec<u8>,  // AES-GCM encrypted
    pub auth_tag: [u8; 16],         // GCM authentication tag
    pub nonce: [u8; 12],            // GCM nonce
}
```

## Testing and Validation

### Protocol Compliance Testing

The test suite validates protocol behavior:

```rust
#[tokio::test]
async fn test_protocol_corruption_recovery() -> UshResult<()> {
    let mut encoder = ProtocolEncoder::new();
    let mut decoder = ProtocolDecoder::new();
    
    let test_message = "Corruption test message";
    let mut frame_data = encoder.encode_text(test_message)?;
    
    // Corrupt some bytes in the middle
    let mid_idx = frame_data.len() / 2;
    frame_data[mid_idx] = 0xFF;
    frame_data[mid_idx + 1] = 0x00;
    
    let messages = decoder.feed_data(&frame_data);
    
    // Verify corrupted messages are properly rejected
    assert!(messages.is_empty() || !messages[0].verify_checksum().unwrap_or(false));
}
```

### Interoperability Testing

Future versions should include:
- **Cross-platform testing**: Different OS audio stacks
- **Hardware variation**: Different speakers/microphones  
- **Environmental testing**: Various noise conditions

## References

1. Simpson, W. (Ed.). (1994). *RFC 1662 - PPP in HDLC-like Framing*. Internet Engineering Task Force. (HDLC framing protocol)

2. International Organization for Standardization. (1993). *ISO/IEC 3309:1993 - Information technology -- Telecommunications and information exchange between systems -- High-level data link control (HDLC) procedures*. (CRC polynomial specification)

3. Peterson, W. W., & Brown, D. T. (1961). "Cyclic codes for error detection." *Proceedings of the IRE*, 49(1), 228-235. (CRC error detection theory)

4. Hopcroft, J. E., Motwani, R., & Ullman, J. D. (2001). *Introduction to Automata Theory, Languages, and Computation* (2nd ed.). Addison-Wesley. (Finite state machines)

5. Stallings, W. (2013). *Data and Computer Communications* (10th ed.). Pearson. (ARQ protocols)

6. Furuhashi, S. (2023). *MessagePack specification*. https://msgpack.org/index.html (Binary serialization format)

7. Google. (2023). *Protocol Buffers*. https://developers.google.com/protocol-buffers (Structured data serialization)