Skip to main content

aivpn_common/
protocol.rs

1//! AIVPN Wire Protocol
2//!
3//! Implements packet format, inner payload encoding, and control messages
4
5use bytes::{BufMut, BytesMut};
6use rand::RngCore;
7use serde::{Deserialize, Serialize};
8
9use crate::crypto::{POLY1305_TAG_SIZE, TAG_SIZE};
10use crate::error::{Error, Result};
11use crate::network_config::ClientNetworkConfig;
12
13/// Maximum UDP packet size (optimized for VPN MTU 1420 + overhead)
14pub const MAX_PACKET_SIZE: usize = 1500;
15
16/// Minimum header overhead (tag + pad_len + inner_header + poly1305)
17pub const MIN_HEADER_OVERHEAD: usize = TAG_SIZE + 2 + 4 + POLY1305_TAG_SIZE;
18
19/// Maximum payload size
20pub const MAX_PAYLOAD_SIZE: usize = MAX_PACKET_SIZE - MIN_HEADER_OVERHEAD;
21
22/// Inner payload types
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
24#[repr(u16)]
25pub enum InnerType {
26    Data = 0x0001,
27    Control = 0x0002,
28    Fragment = 0x0003,
29    Ack = 0x0004,
30}
31
32impl InnerType {
33    pub fn from_u16(value: u16) -> Option<Self> {
34        match value {
35            0x0001 => Some(Self::Data),
36            0x0002 => Some(Self::Control),
37            0x0003 => Some(Self::Fragment),
38            0x0004 => Some(Self::Ack),
39            _ => None,
40        }
41    }
42}
43
44/// Control message subtypes
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
46#[repr(u8)]
47pub enum ControlSubtype {
48    KeyRotate = 0x01,
49    MaskUpdate = 0x02,
50    Keepalive = 0x03,
51    TelemetryRequest = 0x04,
52    TelemetryResponse = 0x05,
53    TimeSync = 0x06,
54    Shutdown = 0x07,
55    ControlAck = 0x08,
56    ServerHello = 0x09,
57    RecordingStart = 0x0A,
58    RecordingAck = 0x0B,
59    RecordingStop = 0x0C,
60    RecordingComplete = 0x0D,
61    RecordingFailed = 0x0E,
62    RecordingStatusRequest = 0x0F,
63    RecordingStatus = 0x10,
64    BootstrapDescriptorUpdate = 0x11,
65}
66
67impl ControlSubtype {
68    pub fn from_u8(value: u8) -> Option<Self> {
69        match value {
70            0x01 => Some(Self::KeyRotate),
71            0x02 => Some(Self::MaskUpdate),
72            0x03 => Some(Self::Keepalive),
73            0x04 => Some(Self::TelemetryRequest),
74            0x05 => Some(Self::TelemetryResponse),
75            0x06 => Some(Self::TimeSync),
76            0x07 => Some(Self::Shutdown),
77            0x08 => Some(Self::ControlAck),
78            0x09 => Some(Self::ServerHello),
79            0x0A => Some(Self::RecordingStart),
80            0x0B => Some(Self::RecordingAck),
81            0x0C => Some(Self::RecordingStop),
82            0x0D => Some(Self::RecordingComplete),
83            0x0E => Some(Self::RecordingFailed),
84            0x0F => Some(Self::RecordingStatusRequest),
85            0x10 => Some(Self::RecordingStatus),
86            0x11 => Some(Self::BootstrapDescriptorUpdate),
87            _ => None,
88        }
89    }
90}
91
92/// Inner payload header (after decryption)
93#[derive(Debug, Clone)]
94pub struct InnerHeader {
95    pub inner_type: InnerType,
96    pub seq_num: u16,
97}
98
99impl InnerHeader {
100    pub fn encode(&self) -> [u8; 4] {
101        let mut buf = [0u8; 4];
102        buf[0..2].copy_from_slice(&(self.inner_type as u16).to_le_bytes());
103        buf[2..4].copy_from_slice(&self.seq_num.to_le_bytes());
104        buf
105    }
106
107    pub fn decode(data: &[u8]) -> Result<Self> {
108        if data.len() < 4 {
109            return Err(Error::InvalidPacket("Inner header too short"));
110        }
111        let inner_type = InnerType::from_u16(u16::from_le_bytes([data[0], data[1]]))
112            .ok_or(Error::InvalidPacket("Unknown inner type"))?;
113        let seq_num = u16::from_le_bytes([data[2], data[3]]);
114        Ok(Self {
115            inner_type,
116            seq_num,
117        })
118    }
119}
120
121/// AIVPN Packet structure
122#[derive(Debug, Clone)]
123pub struct AivpnPacket {
124    pub resonance_tag: [u8; TAG_SIZE],
125    pub mask_dependent_header: Vec<u8>,
126    pub pad_len: u16,
127    pub encrypted_payload: Vec<u8>,
128    pub random_padding: Vec<u8>,
129}
130
131impl AivpnPacket {
132    pub fn new(
133        resonance_tag: [u8; TAG_SIZE],
134        mask_dependent_header: Vec<u8>,
135        encrypted_payload: Vec<u8>,
136        padding_len: u16,
137    ) -> Self {
138        Self {
139            resonance_tag,
140            mask_dependent_header,
141            pad_len: padding_len,
142            encrypted_payload,
143            random_padding: {
144                let mut pad = vec![0u8; padding_len as usize];
145                rand::thread_rng().fill_bytes(&mut pad);
146                pad
147            },
148        }
149    }
150
151    /// Serialize packet to bytes
152    pub fn to_bytes(&self) -> BytesMut {
153        let total_len = TAG_SIZE
154            + self.mask_dependent_header.len()
155            + 2 // pad_len
156            + self.encrypted_payload.len()
157            + self.random_padding.len();
158
159        let mut buf = BytesMut::with_capacity(total_len);
160        buf.put_slice(&self.resonance_tag);
161        buf.put_slice(&self.mask_dependent_header);
162        buf.put_u16_le(self.pad_len);
163        buf.put_slice(&self.encrypted_payload);
164        buf.put_slice(&self.random_padding);
165        buf
166    }
167
168    /// Deserialize packet from bytes
169    pub fn from_bytes(data: &[u8]) -> Result<Self> {
170        if data.len() < TAG_SIZE + 2 {
171            return Err(Error::InvalidPacket("Packet too short"));
172        }
173
174        let mut cursor = 0;
175
176        // Resonance tag
177        let mut resonance_tag = [0u8; TAG_SIZE];
178        resonance_tag.copy_from_slice(&data[cursor..cursor + TAG_SIZE]);
179        cursor += TAG_SIZE;
180
181        // We need to know the mask-dependent header length to parse correctly
182        // This is determined by the active Mask profile
183        // For now, we'll parse it in the server/client with mask context
184        // Return raw data for upper layers to parse
185        let _remaining = &data[cursor..];
186
187        Ok(Self {
188            resonance_tag,
189            mask_dependent_header: Vec::new(),
190            pad_len: 0,
191            encrypted_payload: Vec::new(),
192            random_padding: Vec::new(),
193        })
194    }
195
196    /// Parse with mask context (knowing MDH length)
197    pub fn from_bytes_with_mdh_len(data: &[u8], mdh_len: usize) -> Result<Self> {
198        if data.len() < TAG_SIZE + mdh_len + 2 {
199            return Err(Error::InvalidPacket("Packet too short"));
200        }
201
202        let mut cursor = 0;
203
204        // Resonance tag
205        let mut resonance_tag = [0u8; TAG_SIZE];
206        resonance_tag.copy_from_slice(&data[cursor..cursor + TAG_SIZE]);
207        cursor += TAG_SIZE;
208
209        // Mask-dependent header
210        let mask_dependent_header = data[cursor..cursor + mdh_len].to_vec();
211        cursor += mdh_len;
212
213        // Pad length
214        let pad_len = u16::from_le_bytes([data[cursor], data[cursor + 1]]);
215        cursor += 2;
216
217        // Encrypted payload (everything except padding)
218        let payload_len = data.len() - cursor - pad_len as usize;
219        let encrypted_payload = data[cursor..cursor + payload_len].to_vec();
220        cursor += payload_len;
221
222        // Random padding
223        let random_padding = data[cursor..].to_vec();
224
225        Ok(Self {
226            resonance_tag,
227            mask_dependent_header,
228            pad_len,
229            encrypted_payload,
230            random_padding,
231        })
232    }
233}
234
235/// Control message payload
236#[derive(Debug, Clone, Serialize, Deserialize)]
237pub enum ControlPayload {
238    KeyRotate {
239        new_eph_pub: [u8; 32],
240    },
241    MaskUpdate {
242        mask_data: Vec<u8>,
243        #[serde(with = "serde_bytes")]
244        signature: [u8; 64],
245    },
246    Keepalive,
247    TelemetryRequest {
248        metric_flags: u8,
249    },
250    TelemetryResponse {
251        packet_loss: u16,
252        rtt_ms: u16,
253        jitter_ms: u16,
254        buffer_pct: u8,
255    },
256    TimeSync {
257        server_ts_ms: u64,
258    },
259    Shutdown {
260        reason: u8,
261    },
262    ControlAck {
263        ack_seq: u16,
264        ack_for_subtype: u8,
265    },
266    ServerHello {
267        server_eph_pub: [u8; 32],
268        #[serde(with = "serde_bytes")]
269        signature: [u8; 64],
270        network_config: Option<ClientNetworkConfig>,
271    },
272    /// Admin requests recording start for a service
273    RecordingStart {
274        service: String,
275    },
276    /// Server acknowledges recording start
277    RecordingAck {
278        session_id: [u8; 16],
279        status: String,
280    },
281    /// Admin requests recording stop
282    RecordingStop {
283        session_id: [u8; 16],
284    },
285    /// Server reports mask generation complete
286    RecordingComplete {
287        service: String,
288        mask_id: String,
289        confidence: f32,
290    },
291    /// Server reports recording/generation failure
292    RecordingFailed {
293        reason: String,
294    },
295    /// Client asks whether the current authenticated session may record masks.
296    RecordingStatusRequest,
297    /// Server reports recording capability and current active recording state.
298    RecordingStatus {
299        can_record: bool,
300        active_service: Option<String>,
301    },
302    BootstrapDescriptorUpdate {
303        descriptor_data: Vec<u8>,
304    },
305}
306
307impl ControlPayload {
308    pub fn encode(&self) -> Result<Vec<u8>> {
309        let mut buf = Vec::new();
310
311        match self {
312            Self::KeyRotate { new_eph_pub } => {
313                buf.push(ControlSubtype::KeyRotate as u8);
314                buf.push(0); // reserved
315                buf.extend_from_slice(&(new_eph_pub.len() as u16).to_le_bytes());
316                buf.extend_from_slice(new_eph_pub);
317            }
318            Self::MaskUpdate {
319                mask_data,
320                signature,
321            } => {
322                buf.push(ControlSubtype::MaskUpdate as u8);
323                buf.extend_from_slice(&(mask_data.len() as u16).to_le_bytes());
324                buf.extend_from_slice(mask_data);
325                buf.extend_from_slice(signature);
326            }
327            Self::Keepalive => {
328                buf.push(ControlSubtype::Keepalive as u8);
329            }
330            Self::TelemetryRequest { metric_flags } => {
331                buf.push(ControlSubtype::TelemetryRequest as u8);
332                buf.push(*metric_flags);
333            }
334            Self::TelemetryResponse {
335                packet_loss,
336                rtt_ms,
337                jitter_ms,
338                buffer_pct,
339            } => {
340                buf.push(ControlSubtype::TelemetryResponse as u8);
341                buf.push(0); // flags
342                buf.extend_from_slice(&packet_loss.to_le_bytes());
343                buf.extend_from_slice(&rtt_ms.to_le_bytes());
344                buf.extend_from_slice(&jitter_ms.to_le_bytes());
345                buf.push(*buffer_pct);
346                buf.extend_from_slice(&[0u8; 3]); // reserved
347            }
348            Self::TimeSync { server_ts_ms } => {
349                buf.push(ControlSubtype::TimeSync as u8);
350                buf.extend_from_slice(&server_ts_ms.to_le_bytes());
351            }
352            Self::Shutdown { reason } => {
353                buf.push(ControlSubtype::Shutdown as u8);
354                buf.push(*reason);
355            }
356            Self::ControlAck {
357                ack_seq,
358                ack_for_subtype,
359            } => {
360                buf.push(ControlSubtype::ControlAck as u8);
361                buf.extend_from_slice(&ack_seq.to_le_bytes());
362                buf.push(*ack_for_subtype);
363            }
364            Self::ServerHello {
365                server_eph_pub,
366                signature,
367                network_config,
368            } => {
369                buf.push(ControlSubtype::ServerHello as u8);
370                buf.extend_from_slice(server_eph_pub);
371                buf.extend_from_slice(signature);
372                if let Some(network_config) = network_config {
373                    buf.extend_from_slice(&network_config.encode_wire());
374                }
375            }
376            Self::RecordingStart { service } => {
377                buf.push(ControlSubtype::RecordingStart as u8);
378                let service_bytes = service.as_bytes();
379                buf.extend_from_slice(&(service_bytes.len() as u16).to_le_bytes());
380                buf.extend_from_slice(service_bytes);
381            }
382            Self::RecordingAck { session_id, status } => {
383                buf.push(ControlSubtype::RecordingAck as u8);
384                buf.extend_from_slice(session_id);
385                let status_bytes = status.as_bytes();
386                buf.extend_from_slice(&(status_bytes.len() as u16).to_le_bytes());
387                buf.extend_from_slice(status_bytes);
388            }
389            Self::RecordingStop { session_id } => {
390                buf.push(ControlSubtype::RecordingStop as u8);
391                buf.extend_from_slice(session_id);
392            }
393            Self::RecordingComplete {
394                service,
395                mask_id,
396                confidence,
397            } => {
398                buf.push(ControlSubtype::RecordingComplete as u8);
399                let service_bytes = service.as_bytes();
400                buf.extend_from_slice(&(service_bytes.len() as u16).to_le_bytes());
401                buf.extend_from_slice(service_bytes);
402                let mask_id_bytes = mask_id.as_bytes();
403                buf.extend_from_slice(&(mask_id_bytes.len() as u16).to_le_bytes());
404                buf.extend_from_slice(mask_id_bytes);
405                buf.extend_from_slice(&confidence.to_le_bytes());
406            }
407            Self::RecordingFailed { reason } => {
408                buf.push(ControlSubtype::RecordingFailed as u8);
409                let reason_bytes = reason.as_bytes();
410                buf.extend_from_slice(&(reason_bytes.len() as u16).to_le_bytes());
411                buf.extend_from_slice(reason_bytes);
412            }
413            Self::RecordingStatusRequest => {
414                buf.push(ControlSubtype::RecordingStatusRequest as u8);
415            }
416            Self::RecordingStatus {
417                can_record,
418                active_service,
419            } => {
420                buf.push(ControlSubtype::RecordingStatus as u8);
421                let mut flags = 0u8;
422                if *can_record {
423                    flags |= 0x01;
424                }
425                if active_service.is_some() {
426                    flags |= 0x02;
427                }
428                buf.push(flags);
429                if let Some(service) = active_service {
430                    let service_bytes = service.as_bytes();
431                    buf.extend_from_slice(&(service_bytes.len() as u16).to_le_bytes());
432                    buf.extend_from_slice(service_bytes);
433                }
434            }
435            Self::BootstrapDescriptorUpdate { descriptor_data } => {
436                buf.push(ControlSubtype::BootstrapDescriptorUpdate as u8);
437                buf.extend_from_slice(&(descriptor_data.len() as u16).to_le_bytes());
438                buf.extend_from_slice(descriptor_data);
439            }
440        }
441
442        Ok(buf)
443    }
444
445    pub fn decode(data: &[u8]) -> Result<Self> {
446        if data.is_empty() {
447            return Err(Error::InvalidPacket("Empty control payload"));
448        }
449
450        let subtype = ControlSubtype::from_u8(data[0])
451            .ok_or(Error::InvalidPacket("Unknown control subtype"))?;
452
453        match subtype {
454            ControlSubtype::KeyRotate => {
455                if data.len() < 6 {
456                    return Err(Error::InvalidPacket("KeyRotate too short"));
457                }
458                let new_eph_pub_len = u16::from_le_bytes([data[2], data[3]]) as usize;
459                if data.len() < 4 + new_eph_pub_len {
460                    return Err(Error::InvalidPacket("KeyRotate invalid length"));
461                }
462                let mut new_eph_pub = [0u8; 32];
463                new_eph_pub.copy_from_slice(&data[4..4 + 32]);
464                Ok(Self::KeyRotate { new_eph_pub })
465            }
466            ControlSubtype::MaskUpdate => {
467                if data.len() < 4 {
468                    return Err(Error::InvalidPacket("MaskUpdate too short"));
469                }
470                let mask_len = u16::from_le_bytes([data[1], data[2]]) as usize;
471                if data.len() < 3 + mask_len + 64 {
472                    return Err(Error::InvalidPacket("MaskUpdate invalid length"));
473                }
474                let mask_data = data[3..3 + mask_len].to_vec();
475                let mut signature = [0u8; 64];
476                signature.copy_from_slice(&data[3 + mask_len..3 + mask_len + 64]);
477                Ok(Self::MaskUpdate {
478                    mask_data,
479                    signature,
480                })
481            }
482            ControlSubtype::Keepalive => Ok(Self::Keepalive),
483            ControlSubtype::TelemetryRequest => {
484                if data.len() < 2 {
485                    return Err(Error::InvalidPacket("TelemetryRequest too short"));
486                }
487                Ok(Self::TelemetryRequest {
488                    metric_flags: data[1],
489                })
490            }
491            ControlSubtype::TelemetryResponse => {
492                if data.len() < 12 {
493                    return Err(Error::InvalidPacket("TelemetryResponse too short"));
494                }
495                Ok(Self::TelemetryResponse {
496                    packet_loss: u16::from_le_bytes([data[2], data[3]]),
497                    rtt_ms: u16::from_le_bytes([data[4], data[5]]),
498                    jitter_ms: u16::from_le_bytes([data[6], data[7]]),
499                    buffer_pct: data[8],
500                })
501            }
502            ControlSubtype::TimeSync => {
503                if data.len() < 9 {
504                    return Err(Error::InvalidPacket("TimeSync too short"));
505                }
506                Ok(Self::TimeSync {
507                    server_ts_ms: u64::from_le_bytes(data[1..9].try_into().unwrap()),
508                })
509            }
510            ControlSubtype::Shutdown => {
511                if data.len() < 2 {
512                    return Err(Error::InvalidPacket("Shutdown too short"));
513                }
514                Ok(Self::Shutdown { reason: data[1] })
515            }
516            ControlSubtype::ControlAck => {
517                if data.len() < 4 {
518                    return Err(Error::InvalidPacket("ControlAck too short"));
519                }
520                Ok(Self::ControlAck {
521                    ack_seq: u16::from_le_bytes([data[1], data[2]]),
522                    ack_for_subtype: data[3],
523                })
524            }
525            ControlSubtype::ServerHello => {
526                if data.len() < 1 + 32 + 64 {
527                    return Err(Error::InvalidPacket("ServerHello too short"));
528                }
529                let mut server_eph_pub = [0u8; 32];
530                server_eph_pub.copy_from_slice(&data[1..33]);
531                let mut signature = [0u8; 64];
532                signature.copy_from_slice(&data[33..97]);
533                let network_config = if data.len() >= 97 + ClientNetworkConfig::WIRE_SIZE {
534                    Some(ClientNetworkConfig::decode_wire(
535                        &data[97..97 + ClientNetworkConfig::WIRE_SIZE],
536                    )?)
537                } else {
538                    None
539                };
540                Ok(Self::ServerHello {
541                    server_eph_pub,
542                    signature,
543                    network_config,
544                })
545            }
546            ControlSubtype::RecordingStart => {
547                if data.len() < 3 {
548                    return Err(Error::InvalidPacket("RecordingStart too short"));
549                }
550                let svc_len = u16::from_le_bytes([data[1], data[2]]) as usize;
551                if data.len() < 3 + svc_len {
552                    return Err(Error::InvalidPacket("RecordingStart invalid length"));
553                }
554                let service = String::from_utf8_lossy(&data[3..3 + svc_len]).to_string();
555                Ok(Self::RecordingStart { service })
556            }
557            ControlSubtype::RecordingAck => {
558                if data.len() < 1 + 16 + 2 {
559                    return Err(Error::InvalidPacket("RecordingAck too short"));
560                }
561                let mut session_id = [0u8; 16];
562                session_id.copy_from_slice(&data[1..17]);
563                let status_len = u16::from_le_bytes([data[17], data[18]]) as usize;
564                if data.len() < 19 + status_len {
565                    return Err(Error::InvalidPacket("RecordingAck invalid length"));
566                }
567                let status = String::from_utf8_lossy(&data[19..19 + status_len]).to_string();
568                Ok(Self::RecordingAck { session_id, status })
569            }
570            ControlSubtype::RecordingStop => {
571                if data.len() < 17 {
572                    return Err(Error::InvalidPacket("RecordingStop too short"));
573                }
574                let mut session_id = [0u8; 16];
575                session_id.copy_from_slice(&data[1..17]);
576                Ok(Self::RecordingStop { session_id })
577            }
578            ControlSubtype::RecordingComplete => {
579                if data.len() < 3 {
580                    return Err(Error::InvalidPacket("RecordingComplete too short"));
581                }
582                let mut cursor = 1;
583                let svc_len = u16::from_le_bytes([data[cursor], data[cursor + 1]]) as usize;
584                cursor += 2;
585                if data.len() < cursor + svc_len + 2 + 4 {
586                    return Err(Error::InvalidPacket("RecordingComplete invalid length"));
587                }
588                let service = String::from_utf8_lossy(&data[cursor..cursor + svc_len]).to_string();
589                cursor += svc_len;
590                let mid_len = u16::from_le_bytes([data[cursor], data[cursor + 1]]) as usize;
591                cursor += 2;
592                if data.len() < cursor + mid_len + 4 {
593                    return Err(Error::InvalidPacket("RecordingComplete invalid mask_id"));
594                }
595                let mask_id = String::from_utf8_lossy(&data[cursor..cursor + mid_len]).to_string();
596                cursor += mid_len;
597                let confidence = f32::from_le_bytes([
598                    data[cursor],
599                    data[cursor + 1],
600                    data[cursor + 2],
601                    data[cursor + 3],
602                ]);
603                Ok(Self::RecordingComplete {
604                    service,
605                    mask_id,
606                    confidence,
607                })
608            }
609            ControlSubtype::RecordingFailed => {
610                if data.len() < 3 {
611                    return Err(Error::InvalidPacket("RecordingFailed too short"));
612                }
613                let reason_len = u16::from_le_bytes([data[1], data[2]]) as usize;
614                if data.len() < 3 + reason_len {
615                    return Err(Error::InvalidPacket("RecordingFailed invalid length"));
616                }
617                let reason = String::from_utf8_lossy(&data[3..3 + reason_len]).to_string();
618                Ok(Self::RecordingFailed { reason })
619            }
620            ControlSubtype::RecordingStatusRequest => Ok(Self::RecordingStatusRequest),
621            ControlSubtype::RecordingStatus => {
622                if data.len() < 2 {
623                    return Err(Error::InvalidPacket("RecordingStatus too short"));
624                }
625                let flags = data[1];
626                let can_record = (flags & 0x01) != 0;
627                let has_service = (flags & 0x02) != 0;
628                let active_service = if has_service {
629                    if data.len() < 4 {
630                        return Err(Error::InvalidPacket(
631                            "RecordingStatus missing service length",
632                        ));
633                    }
634                    let service_len = u16::from_le_bytes([data[2], data[3]]) as usize;
635                    if data.len() < 4 + service_len {
636                        return Err(Error::InvalidPacket(
637                            "RecordingStatus invalid service length",
638                        ));
639                    }
640                    Some(String::from_utf8_lossy(&data[4..4 + service_len]).to_string())
641                } else {
642                    None
643                };
644                Ok(Self::RecordingStatus {
645                    can_record,
646                    active_service,
647                })
648            }
649            ControlSubtype::BootstrapDescriptorUpdate => {
650                if data.len() < 3 {
651                    return Err(Error::InvalidPacket("BootstrapDescriptorUpdate too short"));
652                }
653                let descriptor_len = u16::from_le_bytes([data[1], data[2]]) as usize;
654                if data.len() < 3 + descriptor_len {
655                    return Err(Error::InvalidPacket(
656                        "BootstrapDescriptorUpdate invalid length",
657                    ));
658                }
659                Ok(Self::BootstrapDescriptorUpdate {
660                    descriptor_data: data[3..3 + descriptor_len].to_vec(),
661                })
662            }
663        }
664    }
665}
666
667/// ACK packet for selective acknowledgment
668#[derive(Debug, Clone)]
669pub struct AckPacket {
670    pub ack_seq: u16,
671    pub ack_base: u16,
672    pub bitmap: Vec<u8>,
673}
674
675impl AckPacket {
676    pub fn new(ack_seq: u16, ack_base: u16, bitmap: Vec<u8>) -> Self {
677        Self {
678            ack_seq,
679            ack_base,
680            bitmap,
681        }
682    }
683
684    pub fn encode(&self) -> Vec<u8> {
685        let mut buf = Vec::with_capacity(5 + self.bitmap.len());
686        buf.extend_from_slice(&(InnerType::Ack as u16).to_le_bytes());
687        buf.extend_from_slice(&self.ack_seq.to_le_bytes());
688        buf.extend_from_slice(&self.ack_base.to_le_bytes());
689        buf.push(self.bitmap.len() as u8);
690        buf.extend_from_slice(&self.bitmap);
691        buf
692    }
693
694    pub fn decode(data: &[u8]) -> Result<Self> {
695        if data.len() < 5 {
696            return Err(Error::InvalidPacket("ACK too short"));
697        }
698        let ack_seq = u16::from_le_bytes([data[2], data[3]]);
699        let ack_base = u16::from_le_bytes([data[4], data[5]]);
700        let bitmap_len = data[6] as usize;
701        if data.len() < 7 + bitmap_len {
702            return Err(Error::InvalidPacket("ACK invalid length"));
703        }
704        let bitmap = data[7..7 + bitmap_len].to_vec();
705        Ok(Self {
706            ack_seq,
707            ack_base,
708            bitmap,
709        })
710    }
711}