ironrdp_rdpsnd/pdu/
mod.rs

1//! Audio Output Virtual Channel Extension PDUs  [MS-RDPEA][1] implementation.
2//!
3//! [1]: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpea/bea2d5cf-e3b9-4419-92e5-0e074ff9bc5b
4
5use std::borrow::Cow;
6use std::fmt;
7
8use bitflags::bitflags;
9use ironrdp_core::{
10    cast_length, ensure_fixed_part_size, ensure_size, invalid_field_err, other_err, Decode, DecodeError, DecodeResult,
11    Encode, EncodeResult, ReadCursor, WriteCursor,
12};
13use ironrdp_pdu::{read_padding, write_padding};
14use ironrdp_svc::SvcEncode;
15
16const SNDC_FORMATS: u8 = 0x07;
17const SNDC_QUALITYMODE: u8 = 0x0C;
18const SNDC_CRYPTKEY: u8 = 0x08;
19const SNDC_TRAINING: u8 = 0x06;
20const SNDC_WAVE: u8 = 0x02;
21const SNDC_WAVECONFIRM: u8 = 0x05;
22const SNDC_WAVEENCRYPT: u8 = 0x09;
23const SNDC_CLOSE: u8 = 0x01;
24const SNDC_WAVE2: u8 = 0x0D;
25const SNDC_VOLUME: u8 = 0x03;
26const SNDC_PITCH: u8 = 0x04;
27
28// TODO: UDP PDUs
29
30#[repr(u16)]
31#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq)]
32pub enum Version {
33    V2 = 0x02,
34    V5 = 0x05,
35    V6 = 0x06,
36    V8 = 0x08,
37}
38
39impl TryFrom<u16> for Version {
40    type Error = DecodeError;
41
42    fn try_from(value: u16) -> Result<Self, Self::Error> {
43        match value {
44            0x02 => Ok(Self::V2),
45            0x05 => Ok(Self::V5),
46            0x06 => Ok(Self::V6),
47            0x08 => Ok(Self::V8),
48            _ => Err(invalid_field_err!("Version", "unknown audio output version")),
49        }
50    }
51}
52
53impl From<Version> for u16 {
54    fn from(version: Version) -> Self {
55        version as u16
56    }
57}
58
59// format tag:
60// http://tools.ietf.org/html/rfc2361
61#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
62pub struct WaveFormat(u16);
63
64macro_rules! wave_formats {
65    (
66        $(
67            ($konst:ident, $num:expr);
68        )+
69    ) => {
70        impl WaveFormat {
71        $(
72            pub const $konst: WaveFormat = WaveFormat($num);
73        )+
74
75            fn as_str(&self) -> Option<&'static str> {
76                match self.0 {
77                    $(
78                        $num => Some(stringify!($konst)),
79                    )+
80                        _ => None
81                }
82            }
83        }
84    }
85}
86
87wave_formats! {
88    (UNKNOWN, 0x0000);
89    (PCM, 0x0001);
90    (ADPCM, 0x0002);
91    (IEEE_FLOAT, 0x0003);
92    (VSELP, 0x0004);
93    (IBM_CVSD, 0x0005);
94    (ALAW, 0x0006);
95    (MULAW, 0x0007);
96    (OKI_ADPCM, 0x0010);
97    (DVI_ADPCM, 0x0011);
98    (MEDIASPACE_ADPCM, 0x0012);
99    (SIERRA_ADPCM, 0x0013);
100    (G723_ADPCM, 0x0014);
101    (DIGISTD, 0x0015);
102    (DIGIFIX, 0x0016);
103    (DIALOGIC_OKI_ADPCM, 0x0017);
104    (MEDIAVISION_ADPCM, 0x0018);
105    (CU_CODEC, 0x0019);
106    (YAMAHA_ADPCM, 0x0020);
107    (SONARC, 0x0021);
108    (DSPGROUP_TRUESPEECH, 0x0022);
109    (ECHOSC1, 0x0023);
110    (AUDIOFILE_AF36, 0x0024);
111    (APTX, 0x0025);
112    (AUDIOFILE_AF10, 0x0026);
113    (PROSODY_1612, 0x0027);
114    (LRC, 0x0028);
115    (DOLBY_AC2, 0x0030);
116    (GSM610, 0x0031);
117    (MSNAUDIO, 0x0032);
118    (ANTEX_ADPCME, 0x0033);
119    (CONTROL_RES_VQLPC, 0x0034);
120    (DIGIREAL, 0x0035);
121    (DIGIADPCM, 0x0036);
122    (CONTROL_RES_CR10, 0x0037);
123    (NMS_VBXADPCM, 0x0038);
124    (ROLAND_RDAC, 0x0039);
125    (ECHOSC3, 0x003A);
126    (ROCKWELL_ADPCM, 0x003B);
127    (ROCKWELL_DIGITALK, 0x003C);
128    (XEBEC, 0x003D);
129    (G721_ADPCM, 0x0040);
130    (G728_CELP, 0x0041);
131    (MSG723, 0x0042);
132    (MPEG, 0x0050);
133    (RT24, 0x0052);
134    (PAC, 0x0053);
135    (MPEGLAYER3, 0x0055);
136    (LUCENT_G723, 0x0059);
137    (CIRRUS, 0x0060);
138    (ESPCM, 0x0061);
139    (VOXWARE, 0x0062);
140    (CANOPUS_ATRAC, 0x0063);
141    (G726_ADPCM, 0x0064);
142    (G722_ADPCM, 0x0065);
143    (DSAT, 0x0066);
144    (DSAT_DISPLAY, 0x0067);
145    (VOXWARE_BYTE_ALIGNED, 0x0069);
146    (VOXWARE_AC8, 0x0070);
147    (VOXWARE_AC10, 0x0071);
148    (VOXWARE_AC16, 0x0072);
149    (VOXWARE_AC20, 0x0073);
150    (VOXWARE_RT24, 0x0074);
151    (VOXWARE_RT29, 0x0075);
152    (VOXWARE_RT29HW, 0x0076);
153    (VOXWARE_VR12, 0x0077);
154    (VOXWARE_VR18, 0x0078);
155    (VOXWARE_TQ40, 0x0079);
156    (SOFTSOUND, 0x0080);
157    (VOXWARE_TQ60, 0x0081);
158    (MSRT24, 0x0082);
159    (G729A, 0x0083);
160    (MVI_MV12, 0x0084);
161    (DF_G726, 0x0085);
162    (DF_GSM610, 0x0086);
163    (ISIAUDIO, 0x0088);
164    (ONLIVE, 0x0089);
165    (SBC24, 0x0091);
166    (DOLBY_AC3_SPDIF, 0x0092);
167    (ZYXEL_ADPCM, 0x0097);
168    (PHILIPS_LPCBB, 0x0098);
169    (PACKED, 0x0099);
170    (RHETOREX_ADPCM, 0x0100);
171    (IRAT, 0x0101);
172    (VIVO_G723, 0x0111);
173    (VIVO_SIREN, 0x0112);
174    (DIGITAL_G723, 0x0123);
175    (WMAUDIO2, 0x0161);
176    (WMAUDIO3, 0x0162);
177    (WMAUDIO_LOSSLESS, 0x0163);
178    (CREATIVE_ADPCM, 0x0200);
179    (CREATIVE_FASTSPEECH8, 0x0202);
180    (CREATIVE_FASTSPEECH10, 0x0203);
181    (QUARTERDECK, 0x0220);
182    (FM_TOWNS_SND, 0x0300);
183    (BTV_DIGITAL, 0x0400);
184    (VME_VMPCM, 0x0680);
185    (OLIGSM, 0x1000);
186    (OLIADPCM, 0x1001);
187    (OLICELP, 0x1002);
188    (OLISBC, 0x1003);
189    (OLIOPR, 0x1004);
190    (LH_CODEC, 0x1100);
191    (NORRIS, 0x1400);
192    (SOUNDSPACE_MUSICOMPRESS, 0x1500);
193    (DVM, 0x2000);
194    (OPUS, 0x704F);
195    (AAC_MS, 0xA106);
196    (EXTENSIBLE, 0xFFFE);
197}
198
199impl fmt::Debug for WaveFormat {
200    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201        fmt::Debug::fmt(&self.0, f)
202    }
203}
204
205impl fmt::Display for WaveFormat {
206    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207        write!(f, "{} {}", self.0, self.as_str().unwrap_or("<unknown wave format>"))
208    }
209}
210
211#[derive(Debug, Clone, PartialEq, Eq, Hash)]
212pub struct AudioFormat {
213    pub format: WaveFormat,
214    pub n_channels: u16,
215    pub n_samples_per_sec: u32,
216    pub n_avg_bytes_per_sec: u32,
217    pub n_block_align: u16,
218    pub bits_per_sample: u16,
219    pub data: Option<Vec<u8>>,
220}
221
222impl AudioFormat {
223    const NAME: &'static str = "SERVER_AUDIO_VERSION_AND_FORMATS";
224
225    const FIXED_PART_SIZE: usize =
226        2 /* wFormatTag */
227        + 2 /* nChannels */
228        + 4 /* nSamplesPerSec */
229        + 4 /* nAvgBytesPerSec */
230        + 2 /* nBlockAlign */
231        + 2 /* wBitsPerSample */
232        + 2 /* cbSize */;
233}
234
235impl Encode for AudioFormat {
236    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
237        ensure_size!(in: dst, size: self.size());
238
239        dst.write_u16(self.format.0);
240        dst.write_u16(self.n_channels);
241        dst.write_u32(self.n_samples_per_sec);
242        dst.write_u32(self.n_avg_bytes_per_sec);
243        dst.write_u16(self.n_block_align);
244        dst.write_u16(self.bits_per_sample);
245        let len = self.data.as_ref().map_or(0, |d| d.len());
246        dst.write_u16(cast_length!("AudioFormat::cbSize", len)?);
247        if let Some(data) = &self.data {
248            dst.write_slice(data);
249        }
250
251        Ok(())
252    }
253
254    fn name(&self) -> &'static str {
255        Self::NAME
256    }
257
258    fn size(&self) -> usize {
259        Self::FIXED_PART_SIZE
260            .checked_add(self.data.as_ref().map_or(0, |d| d.len()))
261            .expect("never overflow")
262    }
263}
264
265impl<'de> Decode<'de> for AudioFormat {
266    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
267        ensure_fixed_part_size!(in: src);
268
269        let format = WaveFormat(src.read_u16());
270        let n_channels = src.read_u16();
271        let n_samples_per_sec = src.read_u32();
272        let n_avg_bytes_per_sec = src.read_u32();
273        let n_block_align = src.read_u16();
274        let bits_per_sample = src.read_u16();
275        let cb_size = cast_length!("cbSize", src.read_u16())?;
276
277        ensure_size!(in: src, size: cb_size);
278        let data = if cb_size > 0 {
279            Some(src.read_slice(cb_size).into())
280        } else {
281            None
282        };
283
284        Ok(Self {
285            format,
286            n_channels,
287            n_samples_per_sec,
288            n_avg_bytes_per_sec,
289            n_block_align,
290            bits_per_sample,
291            data,
292        })
293    }
294}
295
296#[derive(Debug, Clone, PartialEq, Eq)]
297pub struct ServerAudioFormatPdu {
298    pub version: Version,
299    pub formats: Vec<AudioFormat>,
300}
301
302impl ServerAudioFormatPdu {
303    const NAME: &'static str = "SERVER_AUDIO_VERSION_AND_FORMATS";
304
305    const FIXED_PART_SIZE: usize =
306        4 /* dwFlags */
307        + 4 /* dwVolume */
308        + 4 /* dwPitch */
309        + 2 /* wDGramPort */
310        + 2 /* wNumberOfFormats */
311        + 1 /* cLastBlockConfirmed */
312        + 2 /* wVersion */
313        + 1 /* bPad */;
314}
315
316impl Encode for ServerAudioFormatPdu {
317    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
318        ensure_size!(in: dst, size: self.size());
319
320        write_padding!(dst, 4); /* flags */
321        write_padding!(dst, 4); /* volume */
322        write_padding!(dst, 4); /* pitch */
323        write_padding!(dst, 2); /* DGramPort */
324        dst.write_u16(cast_length!("AudioFormatPdu::n_formats", self.formats.len())?);
325        write_padding!(dst, 1); /* blockNo */
326        dst.write_u16(self.version.into());
327        write_padding!(dst, 1);
328        for fmt in self.formats.iter() {
329            fmt.encode(dst)?;
330        }
331
332        Ok(())
333    }
334
335    fn name(&self) -> &'static str {
336        Self::NAME
337    }
338
339    fn size(&self) -> usize {
340        Self::FIXED_PART_SIZE
341            .checked_add(self.formats.iter().map(|fmt| fmt.size()).sum::<usize>())
342            .expect("never overflow")
343    }
344}
345
346impl<'de> Decode<'de> for ServerAudioFormatPdu {
347    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
348        ensure_fixed_part_size!(in: src);
349
350        read_padding!(src, 4); /* flags */
351        read_padding!(src, 4); /* volume */
352        read_padding!(src, 4); /* pitch */
353        read_padding!(src, 2); /* DGramPort */
354        let n_formats = src.read_u16();
355        read_padding!(src, 1); /* blockNo */
356        let version = Version::try_from(src.read_u16())?;
357        read_padding!(src, 1);
358        let formats = (0..n_formats)
359            .map(|_| AudioFormat::decode(src))
360            .collect::<DecodeResult<_>>()?;
361
362        Ok(Self { version, formats })
363    }
364}
365
366bitflags! {
367    /// Represents `dwFlags` field of `CLIENT_AUDIO_VERSION_AND_FORMATS` structure.
368    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
369    pub struct AudioFormatFlags: u32 {
370        /// The client is capable of consuming audio data. This flag MUST be set
371        /// for audio data to be transferred.
372        const ALIVE = 0x0000_0001;
373        /// The client is capable of applying a volume change to all the audio
374        /// data that is received.
375        const VOLUME = 0x0000_0002;
376        /// The client is capable of applying a pitch change to all the audio
377        /// data that is received.
378        const PITCH = 0x0000_00004;
379        // The source may set any bits
380        const _ = !0;
381    }
382}
383
384#[derive(Debug, Clone, PartialEq, Eq)]
385pub struct ClientAudioFormatPdu {
386    pub version: Version,
387    pub flags: AudioFormatFlags,
388    pub formats: Vec<AudioFormat>,
389    pub volume_left: u16,
390    pub volume_right: u16,
391    pub pitch: u32,
392    pub dgram_port: u16,
393}
394
395impl ClientAudioFormatPdu {
396    const NAME: &'static str = "CLIENT_AUDIO_VERSION_AND_FORMATS";
397
398    const FIXED_PART_SIZE: usize =
399        4 /* dwFlags */
400        + 4 /* dwVolume */
401        + 4 /* dwPitch */
402        + 2 /* wDGramPort */
403        + 2 /* wNumberOfFormats */
404        + 1 /* cLastBlockConfirmed */
405        + 2 /* wVersion */
406        + 1 /* bPad */;
407}
408
409impl Encode for ClientAudioFormatPdu {
410    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
411        ensure_size!(in: dst, size: self.size());
412
413        dst.write_u32(self.flags.bits());
414        let volume = (u32::from(self.volume_right) << 16) | u32::from(self.volume_left);
415        dst.write_u32(volume);
416        dst.write_u32(self.pitch);
417        dst.write_u16_be(self.dgram_port);
418        dst.write_u16(cast_length!("AudioFormatPdu::n_formats", self.formats.len())?);
419        dst.write_u8(0); /* blockNo */
420        dst.write_u16(self.version.into());
421        write_padding!(dst, 1);
422        for fmt in self.formats.iter() {
423            fmt.encode(dst)?;
424        }
425
426        Ok(())
427    }
428
429    fn name(&self) -> &'static str {
430        Self::NAME
431    }
432
433    fn size(&self) -> usize {
434        Self::FIXED_PART_SIZE
435            .checked_add(self.formats.iter().map(|fmt| fmt.size()).sum::<usize>())
436            .expect("never overflow")
437    }
438}
439
440impl<'de> Decode<'de> for ClientAudioFormatPdu {
441    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
442        ensure_fixed_part_size!(in: src);
443
444        let flags = AudioFormatFlags::from_bits_truncate(src.read_u32());
445        let volume = src.read_u32();
446        let volume_left = (volume & 0xFFFF) as u16;
447        let volume_right = (volume >> 16) as u16;
448        let pitch = src.read_u32();
449        let dgram_port = src.read_u16_be();
450        let n_formats = src.read_u16();
451        let _block_no = src.read_u8();
452        let version = Version::try_from(src.read_u16())?;
453        read_padding!(src, 1);
454        let formats = (0..n_formats)
455            .map(|_| AudioFormat::decode(src))
456            .collect::<DecodeResult<_>>()?;
457
458        Ok(Self {
459            version,
460            flags,
461            formats,
462            volume_left,
463            volume_right,
464            pitch,
465            dgram_port,
466        })
467    }
468}
469
470#[repr(u16)]
471#[derive(Debug, Copy, Clone, PartialEq, Eq)]
472pub enum QualityMode {
473    Dynamic = 0x00,
474    Medium = 0x01,
475    High = 0x02,
476}
477
478impl TryFrom<u16> for QualityMode {
479    type Error = DecodeError;
480
481    fn try_from(value: u16) -> Result<Self, Self::Error> {
482        match value {
483            0x00 => Ok(Self::Dynamic),
484            0x01 => Ok(Self::Medium),
485            0x02 => Ok(Self::High),
486            _ => Err(invalid_field_err!("QualityMode", "unknown audio quality mode")),
487        }
488    }
489}
490
491impl From<QualityMode> for u16 {
492    fn from(mode: QualityMode) -> Self {
493        mode as u16
494    }
495}
496
497#[derive(Debug, Clone, PartialEq, Eq)]
498pub struct QualityModePdu {
499    pub quality_mode: QualityMode,
500}
501
502impl QualityModePdu {
503    const NAME: &'static str = "AUDIO_QUALITY_MODE";
504
505    const FIXED_PART_SIZE: usize =
506        2 /* wQualityMode */
507        + 2 /* reserved */;
508}
509
510impl Encode for QualityModePdu {
511    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
512        ensure_size!(in: dst, size: self.size());
513
514        dst.write_u16(self.quality_mode.into());
515        write_padding!(dst, 2); /* reserved */
516
517        Ok(())
518    }
519
520    fn name(&self) -> &'static str {
521        Self::NAME
522    }
523
524    fn size(&self) -> usize {
525        Self::FIXED_PART_SIZE
526    }
527}
528
529impl<'de> Decode<'de> for QualityModePdu {
530    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
531        ensure_fixed_part_size!(in: src);
532
533        let quality_mode = QualityMode::try_from(src.read_u16())?;
534        read_padding!(src, 2); /* reserved */
535
536        Ok(Self { quality_mode })
537    }
538}
539
540#[derive(Debug, Clone, PartialEq, Eq)]
541pub struct CryptKeyPdu {
542    pub seed: [u8; 32],
543}
544
545impl CryptKeyPdu {
546    const NAME: &'static str = "SNDCRYPT";
547
548    const FIXED_PART_SIZE: usize =
549        4 /* reserved */
550        + 32 /* seed */;
551}
552
553impl Encode for CryptKeyPdu {
554    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
555        ensure_size!(in: dst, size: self.size());
556
557        write_padding!(dst, 4); /* reserved */
558        dst.write_array(self.seed);
559
560        Ok(())
561    }
562
563    fn name(&self) -> &'static str {
564        Self::NAME
565    }
566
567    fn size(&self) -> usize {
568        Self::FIXED_PART_SIZE
569    }
570}
571
572impl<'de> Decode<'de> for CryptKeyPdu {
573    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
574        ensure_fixed_part_size!(in: src);
575
576        read_padding!(src, 4); /* reserved */
577        let seed = src.read_array();
578
579        Ok(Self { seed })
580    }
581}
582
583#[derive(Debug, Clone, PartialEq, Eq)]
584pub struct TrainingPdu {
585    pub timestamp: u16,
586    pub data: Vec<u8>,
587}
588
589impl TrainingPdu {
590    const NAME: &'static str = "SNDTRAINING";
591
592    const FIXED_PART_SIZE: usize =
593        2 /* wTimeStamp */
594        + 2 /* wPackSize */;
595}
596
597impl Encode for TrainingPdu {
598    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
599        ensure_size!(in: dst, size: self.size());
600
601        dst.write_u16(self.timestamp);
602        let len = if self.data.is_empty() {
603            0
604        } else {
605            self.size() + ServerAudioOutputPdu::FIXED_PART_SIZE
606        };
607        dst.write_u16(cast_length!("TrainingPdu::wPackSize", len)?);
608        dst.write_slice(&self.data);
609
610        Ok(())
611    }
612
613    fn name(&self) -> &'static str {
614        Self::NAME
615    }
616
617    fn size(&self) -> usize {
618        Self::FIXED_PART_SIZE
619            .checked_add(self.data.len())
620            .expect("never overflow")
621    }
622}
623
624impl<'de> Decode<'de> for TrainingPdu {
625    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
626        ensure_fixed_part_size!(in: src);
627
628        let timestamp = src.read_u16();
629        let len = src.read_u16() as usize;
630        let data = if len != 0 {
631            if len < Self::FIXED_PART_SIZE + ServerAudioOutputPdu::FIXED_PART_SIZE {
632                return Err(invalid_field_err!("TrainingPdu::wPackSize", "too small"));
633            }
634            let len = len - Self::FIXED_PART_SIZE - ServerAudioOutputPdu::FIXED_PART_SIZE;
635            ensure_size!(in: src, size: len);
636            src.read_slice(len).into()
637        } else {
638            Vec::new()
639        };
640
641        Ok(Self { timestamp, data })
642    }
643}
644
645#[derive(Debug, Clone, PartialEq, Eq)]
646pub struct TrainingConfirmPdu {
647    pub timestamp: u16,
648    pub pack_size: u16,
649}
650
651impl TrainingConfirmPdu {
652    const NAME: &'static str = "SNDTRAININGCONFIRM";
653
654    const FIXED_PART_SIZE: usize =
655        2 /* wTimeStamp */
656        + 2 /* wPackSize */;
657}
658
659impl Encode for TrainingConfirmPdu {
660    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
661        ensure_size!(in: dst, size: self.size());
662
663        dst.write_u16(self.timestamp);
664        dst.write_u16(self.pack_size);
665
666        Ok(())
667    }
668
669    fn name(&self) -> &'static str {
670        Self::NAME
671    }
672
673    fn size(&self) -> usize {
674        Self::FIXED_PART_SIZE
675    }
676}
677
678impl<'de> Decode<'de> for TrainingConfirmPdu {
679    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
680        ensure_fixed_part_size!(in: src);
681
682        let timestamp = src.read_u16();
683        let pack_size = src.read_u16();
684
685        Ok(Self { timestamp, pack_size })
686    }
687}
688
689#[derive(Debug, Clone, PartialEq, Eq)]
690pub struct WaveInfoPdu {
691    pub timestamp: u16,
692    pub format_no: u16,
693    pub block_no: u8,
694    pub data: [u8; 4],
695}
696
697impl WaveInfoPdu {
698    const NAME: &'static str = "SNDWAVEINFO";
699
700    const FIXED_PART_SIZE: usize =
701        2 /* wTimeStamp */
702        + 2 /* wFormatNo */
703        + 1 /* cBlockNo */
704        + 3 /* bPad */
705        + 4 /* data */;
706}
707
708impl Encode for WaveInfoPdu {
709    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
710        ensure_size!(in: dst, size: self.size());
711
712        dst.write_u16(self.timestamp);
713        dst.write_u16(self.format_no);
714        dst.write_u8(self.block_no);
715        write_padding!(dst, 3);
716        dst.write_array(self.data);
717
718        Ok(())
719    }
720
721    fn name(&self) -> &'static str {
722        Self::NAME
723    }
724
725    fn size(&self) -> usize {
726        Self::FIXED_PART_SIZE
727    }
728}
729
730impl<'de> Decode<'de> for WaveInfoPdu {
731    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
732        ensure_fixed_part_size!(in: src);
733
734        let timestamp = src.read_u16();
735        let format_no = src.read_u16();
736        let block_no = src.read_u8();
737        read_padding!(src, 3);
738        let data = src.read_array();
739
740        Ok(Self {
741            timestamp,
742            format_no,
743            block_no,
744            data,
745        })
746    }
747}
748
749#[derive(Debug, Clone, PartialEq, Eq)]
750pub struct SndWavePdu {
751    pub data: Vec<u8>,
752}
753
754impl SndWavePdu {
755    const NAME: &'static str = "SNDWAVE";
756
757    const FIXED_PART_SIZE: usize = 4 /* bPad */;
758}
759
760impl Encode for SndWavePdu {
761    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
762        ensure_size!(in: dst, size: self.size());
763
764        write_padding!(dst, 4);
765        dst.write_slice(&self.data);
766
767        Ok(())
768    }
769
770    fn name(&self) -> &'static str {
771        Self::NAME
772    }
773
774    fn size(&self) -> usize {
775        Self::FIXED_PART_SIZE
776            .checked_add(self.data.len())
777            .expect("never overflow")
778    }
779}
780
781impl SndWavePdu {
782    fn decode(src: &mut ReadCursor<'_>, data_len: usize) -> DecodeResult<Self> {
783        ensure_fixed_part_size!(in: src);
784
785        read_padding!(src, 4);
786        ensure_size!(in: src, size: data_len);
787        let data = src.read_slice(data_len).into();
788
789        Ok(Self { data })
790    }
791}
792
793// combines WaveInfoPdu + WavePdu
794#[derive(Debug, Clone, PartialEq, Eq)]
795pub struct WavePdu<'a> {
796    pub timestamp: u16,
797    pub format_no: u16,
798    pub block_no: u8,
799    pub data: Cow<'a, [u8]>,
800}
801
802impl WavePdu<'_> {
803    const NAME: &'static str = "WavePdu";
804
805    fn body_size(&self) -> usize {
806        (WaveInfoPdu::FIXED_PART_SIZE - 4)
807            .checked_add(self.data.len())
808            .expect("never overflow")
809    }
810}
811
812impl Encode for WavePdu<'_> {
813    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
814        let info = WaveInfoPdu {
815            timestamp: self.timestamp,
816            format_no: self.format_no,
817            block_no: self.block_no,
818            data: self.data[0..4]
819                .try_into()
820                .map_err(|e| other_err!("invalid data", source: e))?,
821        };
822        let wave = SndWavePdu {
823            data: self.data[4..].into(),
824        };
825        info.encode(dst)?;
826        wave.encode(dst)?;
827        Ok(())
828    }
829
830    fn name(&self) -> &'static str {
831        Self::NAME
832    }
833
834    fn size(&self) -> usize {
835        (WaveInfoPdu::FIXED_PART_SIZE + SndWavePdu::FIXED_PART_SIZE - 4)
836            .checked_add(self.data.len())
837            .expect("never overflow")
838    }
839}
840
841impl WavePdu<'_> {
842    fn decode(src: &mut ReadCursor<'_>, body_size: u16) -> DecodeResult<Self> {
843        let info = WaveInfoPdu::decode(src)?;
844        let body_size = body_size as usize;
845        let data_len = body_size
846            .checked_sub(info.size())
847            .ok_or_else(|| invalid_field_err!("Length", "WaveInfo body_size is too small"))?;
848        let wave = SndWavePdu::decode(src, data_len)?;
849
850        let mut data = Vec::with_capacity(wave.size());
851        data.extend_from_slice(&info.data);
852        data.extend_from_slice(&wave.data);
853
854        Ok(Self {
855            timestamp: info.timestamp,
856            format_no: info.format_no,
857            block_no: info.block_no,
858            data: data.into(),
859        })
860    }
861}
862
863#[derive(Debug, Clone, PartialEq, Eq)]
864pub struct WaveConfirmPdu {
865    pub timestamp: u16,
866    pub block_no: u8,
867}
868
869impl WaveConfirmPdu {
870    const NAME: &'static str = "SNDWAV_CONFIRM";
871
872    const FIXED_PART_SIZE: usize =
873        2 /* wTimeStamp */
874        + 1 /* cConfirmBlockNo */
875        + 1 /* pad */;
876}
877
878impl Encode for WaveConfirmPdu {
879    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
880        ensure_size!(in: dst, size: self.size());
881
882        dst.write_u16(self.timestamp);
883        dst.write_u8(self.block_no);
884        write_padding!(dst, 1);
885
886        Ok(())
887    }
888
889    fn name(&self) -> &'static str {
890        Self::NAME
891    }
892
893    fn size(&self) -> usize {
894        Self::FIXED_PART_SIZE
895    }
896}
897
898impl<'de> Decode<'de> for WaveConfirmPdu {
899    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
900        ensure_fixed_part_size!(in: src);
901
902        let timestamp = src.read_u16();
903        let block_no = src.read_u8();
904        read_padding!(src, 1);
905
906        Ok(Self { timestamp, block_no })
907    }
908}
909
910#[derive(Debug, Clone, PartialEq, Eq)]
911pub struct WaveEncryptPdu {
912    pub timestamp: u16,
913    pub format_no: u16,
914    pub block_no: u8,
915    pub signature: Option<[u8; 8]>,
916    // TODO: use Cow?
917    pub data: Vec<u8>,
918}
919
920impl WaveEncryptPdu {
921    const NAME: &'static str = "SNDWAVECRYPT";
922
923    const FIXED_PART_SIZE: usize =
924        2 /* wTimeStamp */
925        + 2 /* wFormatNo */
926        + 1 /* cBlockNo */
927        + 3 /* bPad */;
928}
929
930impl Encode for WaveEncryptPdu {
931    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
932        ensure_size!(in: dst, size: self.size());
933
934        dst.write_u16(self.timestamp);
935        dst.write_u16(self.format_no);
936        dst.write_u8(self.block_no);
937        write_padding!(dst, 3);
938        if let Some(sig) = self.signature.as_ref() {
939            dst.write_slice(sig);
940        }
941        dst.write_slice(&self.data);
942
943        Ok(())
944    }
945
946    fn name(&self) -> &'static str {
947        Self::NAME
948    }
949
950    fn size(&self) -> usize {
951        Self::FIXED_PART_SIZE
952            .checked_add(self.signature.map_or(0, |_| 8))
953            .unwrap()
954            .checked_add(self.data.len())
955            .expect("never overflow")
956    }
957}
958
959impl WaveEncryptPdu {
960    fn decode(src: &mut ReadCursor<'_>, version: Version) -> DecodeResult<Self> {
961        ensure_fixed_part_size!(in: src);
962
963        let timestamp = src.read_u16();
964        let format_no = src.read_u16();
965        let block_no = src.read_u8();
966        read_padding!(src, 3);
967        let signature = if version >= Version::V5 {
968            ensure_size!(in: src, size: 8);
969            Some(src.read_array())
970        } else {
971            None
972        };
973        let data = src.read_remaining().into();
974
975        Ok(Self {
976            timestamp,
977            format_no,
978            block_no,
979            signature,
980            data,
981        })
982    }
983}
984
985#[derive(Clone, PartialEq, Eq)]
986pub struct Wave2Pdu<'a> {
987    pub timestamp: u16,
988    pub format_no: u16,
989    pub block_no: u8,
990    pub audio_timestamp: u32,
991    pub data: Cow<'a, [u8]>,
992}
993
994impl fmt::Debug for Wave2Pdu<'_> {
995    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
996        f.debug_struct("Wave2Pdu")
997            .field("timestamp", &self.timestamp)
998            .field("format_no", &self.format_no)
999            .field("block_no", &self.block_no)
1000            .field("audio_timestamp", &self.audio_timestamp)
1001            .finish()
1002    }
1003}
1004
1005impl Wave2Pdu<'_> {
1006    const NAME: &'static str = "SNDWAVE2";
1007
1008    const FIXED_PART_SIZE: usize =
1009        2 /* wTimeStamp */
1010        + 2 /* wFormatNo */
1011        + 1 /* cBlockNo */
1012        + 3 /* bPad */
1013        + 4 /* dwAudioTimestamp */;
1014}
1015
1016impl Encode for Wave2Pdu<'_> {
1017    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
1018        ensure_size!(in: dst, size: self.size());
1019
1020        dst.write_u16(self.timestamp);
1021        dst.write_u16(self.format_no);
1022        dst.write_u8(self.block_no);
1023        write_padding!(dst, 3);
1024        dst.write_u32(self.audio_timestamp);
1025        dst.write_slice(&self.data);
1026
1027        Ok(())
1028    }
1029
1030    fn name(&self) -> &'static str {
1031        Self::NAME
1032    }
1033
1034    fn size(&self) -> usize {
1035        Self::FIXED_PART_SIZE
1036            .checked_add(self.data.len())
1037            .expect("never overflow")
1038    }
1039}
1040
1041impl<'de> Decode<'de> for Wave2Pdu<'_> {
1042    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
1043        ensure_fixed_part_size!(in: src);
1044
1045        let timestamp = src.read_u16();
1046        let format_no = src.read_u16();
1047        let block_no = src.read_u8();
1048        read_padding!(src, 3);
1049        let audio_timestamp = src.read_u32();
1050        let data = src.read_remaining().to_vec().into();
1051
1052        Ok(Self {
1053            timestamp,
1054            format_no,
1055            block_no,
1056            audio_timestamp,
1057            data,
1058        })
1059    }
1060}
1061
1062#[derive(Debug, Clone, PartialEq, Eq)]
1063pub struct VolumePdu {
1064    pub volume_left: u16,
1065    pub volume_right: u16,
1066}
1067
1068impl VolumePdu {
1069    const NAME: &'static str = "SNDVOL";
1070
1071    const FIXED_PART_SIZE: usize = 4;
1072}
1073
1074impl Encode for VolumePdu {
1075    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
1076        ensure_size!(in: dst, size: self.size());
1077
1078        let volume = (u32::from(self.volume_right) << 16) | u32::from(self.volume_left);
1079        dst.write_u32(volume);
1080
1081        Ok(())
1082    }
1083
1084    fn name(&self) -> &'static str {
1085        Self::NAME
1086    }
1087
1088    fn size(&self) -> usize {
1089        Self::FIXED_PART_SIZE
1090    }
1091}
1092
1093impl<'de> Decode<'de> for VolumePdu {
1094    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
1095        ensure_fixed_part_size!(in: src);
1096
1097        let volume = src.read_u32();
1098        let volume_left = (volume & 0xFFFF) as u16;
1099        let volume_right = (volume >> 16) as u16;
1100
1101        Ok(Self {
1102            volume_left,
1103            volume_right,
1104        })
1105    }
1106}
1107
1108#[derive(Debug, Clone, PartialEq, Eq)]
1109pub struct PitchPdu {
1110    pub pitch: u32,
1111}
1112
1113impl PitchPdu {
1114    const NAME: &'static str = "SNDPITCH";
1115
1116    const FIXED_PART_SIZE: usize = 4;
1117}
1118
1119impl Encode for PitchPdu {
1120    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
1121        ensure_size!(in: dst, size: self.size());
1122
1123        dst.write_u32(self.pitch);
1124
1125        Ok(())
1126    }
1127
1128    fn name(&self) -> &'static str {
1129        Self::NAME
1130    }
1131
1132    fn size(&self) -> usize {
1133        Self::FIXED_PART_SIZE
1134    }
1135}
1136
1137impl<'de> Decode<'de> for PitchPdu {
1138    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
1139        ensure_fixed_part_size!(in: src);
1140
1141        let pitch = src.read_u32();
1142
1143        Ok(Self { pitch })
1144    }
1145}
1146
1147/// Server Audio Output Channel message (PDU prefixed with `SNDPROLOG`)
1148#[derive(Debug, Clone, PartialEq, Eq)]
1149pub enum ServerAudioOutputPdu<'a> {
1150    AudioFormat(ServerAudioFormatPdu),
1151    CryptKey(CryptKeyPdu),
1152    Training(TrainingPdu),
1153    Wave(WavePdu<'a>),
1154    WaveEncrypt(WaveEncryptPdu),
1155    Close,
1156    Wave2(Wave2Pdu<'a>),
1157    Volume(VolumePdu),
1158    Pitch(PitchPdu),
1159}
1160
1161impl ServerAudioOutputPdu<'_> {
1162    const NAME: &'static str = "ServerAudioOutputPdu";
1163
1164    const FIXED_PART_SIZE: usize = 1 /* msgType */ + 1 /* padding*/ + 2 /* bodySize */;
1165}
1166
1167impl Encode for ServerAudioOutputPdu<'_> {
1168    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
1169        ensure_fixed_part_size!(in: dst);
1170
1171        let (msg_type, pdu_size) = match self {
1172            Self::AudioFormat(pdu) => (SNDC_FORMATS, pdu.size()),
1173            Self::CryptKey(pdu) => (SNDC_CRYPTKEY, pdu.size()),
1174            Self::Training(pdu) => (SNDC_TRAINING, pdu.size()),
1175            Self::Wave(pdu) => (SNDC_WAVE, pdu.body_size()),
1176            Self::WaveEncrypt(pdu) => (SNDC_WAVEENCRYPT, pdu.size()),
1177            Self::Close => (SNDC_CLOSE, 0),
1178            Self::Wave2(pdu) => (SNDC_WAVE2, pdu.size()),
1179            Self::Volume(pdu) => (SNDC_VOLUME, pdu.size()),
1180            Self::Pitch(pdu) => (SNDC_PITCH, pdu.size()),
1181        };
1182
1183        dst.write_u8(msg_type);
1184        write_padding!(dst, 1);
1185        dst.write_u16(cast_length!("ServerAudioOutputPdu::bodySize", pdu_size)?);
1186
1187        match self {
1188            Self::AudioFormat(pdu) => pdu.encode(dst),
1189            Self::CryptKey(pdu) => pdu.encode(dst),
1190            Self::Training(pdu) => pdu.encode(dst),
1191            Self::Wave(pdu) => pdu.encode(dst),
1192            Self::WaveEncrypt(pdu) => pdu.encode(dst),
1193            Self::Close => Ok(()),
1194            Self::Wave2(pdu) => pdu.encode(dst),
1195            Self::Volume(pdu) => pdu.encode(dst),
1196            Self::Pitch(pdu) => pdu.encode(dst),
1197        }?;
1198
1199        Ok(())
1200    }
1201
1202    fn name(&self) -> &'static str {
1203        Self::NAME
1204    }
1205
1206    fn size(&self) -> usize {
1207        Self::FIXED_PART_SIZE
1208            .checked_add(match self {
1209                Self::AudioFormat(pdu) => pdu.size(),
1210                Self::CryptKey(pdu) => pdu.size(),
1211                Self::Training(pdu) => pdu.size(),
1212                Self::Wave(pdu) => pdu.size(),
1213                Self::WaveEncrypt(pdu) => pdu.size(),
1214                Self::Close => 0,
1215                Self::Wave2(pdu) => pdu.size(),
1216                Self::Volume(pdu) => pdu.size(),
1217                Self::Pitch(pdu) => pdu.size(),
1218            })
1219            .expect("never overflow")
1220    }
1221}
1222
1223impl<'de> Decode<'de> for ServerAudioOutputPdu<'_> {
1224    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
1225        ensure_fixed_part_size!(in: src);
1226
1227        let msg_type = src.read_u8();
1228        read_padding!(src, 1);
1229        let body_size = src.read_u16();
1230
1231        match msg_type {
1232            SNDC_FORMATS => {
1233                let pdu = ServerAudioFormatPdu::decode(src)?;
1234                Ok(Self::AudioFormat(pdu))
1235            }
1236            SNDC_CRYPTKEY => {
1237                let pdu = CryptKeyPdu::decode(src)?;
1238                Ok(Self::CryptKey(pdu))
1239            }
1240            SNDC_TRAINING => {
1241                let pdu = TrainingPdu::decode(src)?;
1242                Ok(Self::Training(pdu))
1243            }
1244            SNDC_WAVE => {
1245                let pdu = WavePdu::decode(src, body_size)?;
1246                Ok(Self::Wave(pdu))
1247            }
1248            SNDC_WAVEENCRYPT => {
1249                let pdu = WaveEncryptPdu::decode(src, Version::V5)?;
1250                Ok(Self::WaveEncrypt(pdu))
1251            }
1252            SNDC_CLOSE => Ok(Self::Close),
1253            SNDC_WAVE2 => {
1254                let pdu = Wave2Pdu::decode(src)?;
1255                Ok(Self::Wave2(pdu))
1256            }
1257            SNDC_VOLUME => {
1258                let pdu = VolumePdu::decode(src)?;
1259                Ok(Self::Volume(pdu))
1260            }
1261            SNDC_PITCH => {
1262                let pdu = PitchPdu::decode(src)?;
1263                Ok(Self::Pitch(pdu))
1264            }
1265            _ => Err(invalid_field_err!(
1266                "ServerAudioOutputPdu::msgType",
1267                "Unknown audio output PDU type"
1268            )),
1269        }
1270    }
1271}
1272
1273impl SvcEncode for ServerAudioOutputPdu<'_> {}
1274
1275/// Client Audio Output Channel message (PDU prefixed with `SNDPROLOG`)
1276#[derive(Debug, Clone, PartialEq, Eq)]
1277pub enum ClientAudioOutputPdu {
1278    AudioFormat(ClientAudioFormatPdu),
1279    QualityMode(QualityModePdu),
1280    TrainingConfirm(TrainingConfirmPdu),
1281    WaveConfirm(WaveConfirmPdu),
1282}
1283
1284impl ClientAudioOutputPdu {
1285    const NAME: &'static str = "ClientAudioOutputPdu";
1286
1287    const FIXED_PART_SIZE: usize = 1 /* msgType */ + 1 /* padding*/ + 2 /* bodySize */;
1288}
1289
1290impl Encode for ClientAudioOutputPdu {
1291    fn encode(&self, dst: &mut WriteCursor<'_>) -> EncodeResult<()> {
1292        ensure_fixed_part_size!(in: dst);
1293
1294        let (msg_type, body_size) = match self {
1295            Self::AudioFormat(pdu) => (SNDC_FORMATS, pdu.size()),
1296            Self::QualityMode(pdu) => (SNDC_QUALITYMODE, pdu.size()),
1297            Self::TrainingConfirm(pdu) => (SNDC_TRAINING, pdu.size()),
1298            Self::WaveConfirm(pdu) => (SNDC_WAVECONFIRM, pdu.size()),
1299        };
1300
1301        dst.write_u8(msg_type);
1302        write_padding!(dst, 1);
1303        dst.write_u16(cast_length!("ClientAudioOutputPdu::bodySize", body_size)?);
1304
1305        match self {
1306            Self::AudioFormat(pdu) => pdu.encode(dst),
1307            Self::QualityMode(pdu) => pdu.encode(dst),
1308            Self::TrainingConfirm(pdu) => pdu.encode(dst),
1309            Self::WaveConfirm(pdu) => pdu.encode(dst),
1310        }?;
1311
1312        Ok(())
1313    }
1314
1315    fn name(&self) -> &'static str {
1316        Self::NAME
1317    }
1318
1319    fn size(&self) -> usize {
1320        Self::FIXED_PART_SIZE
1321            .checked_add(match self {
1322                Self::AudioFormat(pdu) => pdu.size(),
1323                Self::QualityMode(pdu) => pdu.size(),
1324                Self::TrainingConfirm(pdu) => pdu.size(),
1325                Self::WaveConfirm(pdu) => pdu.size(),
1326            })
1327            .expect("never overflow")
1328    }
1329}
1330
1331impl<'de> Decode<'de> for ClientAudioOutputPdu {
1332    fn decode(src: &mut ReadCursor<'de>) -> DecodeResult<Self> {
1333        ensure_fixed_part_size!(in: src);
1334
1335        let msg_type = src.read_u8();
1336        read_padding!(src, 1);
1337        let _body_size = src.read_u16();
1338
1339        match msg_type {
1340            SNDC_FORMATS => {
1341                let pdu = ClientAudioFormatPdu::decode(src)?;
1342                Ok(Self::AudioFormat(pdu))
1343            }
1344            SNDC_QUALITYMODE => {
1345                let pdu = QualityModePdu::decode(src)?;
1346                Ok(Self::QualityMode(pdu))
1347            }
1348            SNDC_TRAINING => {
1349                let pdu = TrainingConfirmPdu::decode(src)?;
1350                Ok(Self::TrainingConfirm(pdu))
1351            }
1352            SNDC_WAVECONFIRM => {
1353                let pdu = WaveConfirmPdu::decode(src)?;
1354                Ok(Self::WaveConfirm(pdu))
1355            }
1356            _ => Err(invalid_field_err!(
1357                "ClientAudioOutputPdu::msgType",
1358                "Unknown audio output PDU type"
1359            )),
1360        }
1361    }
1362}
1363
1364impl SvcEncode for ClientAudioOutputPdu {}