1use ironrdp_core::{impl_as_any, Decode as _, ReadCursor};
2use ironrdp_pdu::gcc::ChannelName;
3use ironrdp_pdu::{decode_err, pdu_other_err, PduResult};
4use ironrdp_svc::{CompressionCondition, SvcMessage, SvcProcessor, SvcProcessorMessages, SvcServerProcessor};
5use tracing::{debug, error};
6
7use crate::pdu::{self, ClientAudioFormatPdu, QualityMode};
8
9pub type RdpsndSvcMessages = SvcProcessorMessages<RdpsndServer>;
10
11pub trait RdpsndError: core::error::Error + Send + Sync + 'static {}
12
13impl<T> RdpsndError for T where T: core::error::Error + Send + Sync + 'static {}
14
15#[derive(Debug)]
17pub enum RdpsndServerMessage {
18 Wave(Vec<u8>, u32),
20 SetVolume {
21 left: u16,
22 right: u16,
23 },
24 Close,
25 Error(Box<dyn RdpsndError>),
29}
30
31pub trait RdpsndServerHandler: Send + core::fmt::Debug {
32 fn get_formats(&self) -> &[pdu::AudioFormat];
33
34 fn start(&mut self, client_format: &ClientAudioFormatPdu) -> Option<u16>;
35
36 fn stop(&mut self);
37}
38
39#[derive(Debug, Copy, Clone, PartialEq, Eq)]
40enum RdpsndState {
41 Start,
42 WaitingForClientFormats,
43 WaitingForQualityMode,
44 WaitingForTrainingConfirm,
45 Ready,
46 Stop,
47}
48
49#[derive(Debug)]
50pub struct RdpsndServer {
51 handler: Box<dyn RdpsndServerHandler>,
52 state: RdpsndState,
53 client_format: Option<ClientAudioFormatPdu>,
54 quality_mode: Option<QualityMode>,
55 block_no: u8,
56 format_no: Option<u16>,
57}
58
59impl RdpsndServer {
60 pub const NAME: ChannelName = ChannelName::from_static(b"rdpsnd\0\0");
61
62 pub fn new(handler: Box<dyn RdpsndServerHandler>) -> Self {
63 Self {
64 handler,
65 state: RdpsndState::Start,
66 client_format: None,
67 quality_mode: None,
68 format_no: None,
69 block_no: 0,
70 }
71 }
72
73 pub fn version(&self) -> PduResult<pdu::Version> {
74 let client_format = self
75 .client_format
76 .as_ref()
77 .ok_or_else(|| pdu_other_err!("invalid state, client format not yet received"))?;
78
79 Ok(client_format.version)
80 }
81
82 pub fn flags(&self) -> PduResult<pdu::AudioFormatFlags> {
83 let client_format = self
84 .client_format
85 .as_ref()
86 .ok_or_else(|| pdu_other_err!("invalid state, client format not yet received"))?;
87
88 Ok(client_format.flags)
89 }
90
91 pub fn training_pdu(&mut self) -> PduResult<RdpsndSvcMessages> {
92 let pdu = pdu::TrainingPdu {
93 timestamp: 4231, data: vec![],
95 };
96 Ok(RdpsndSvcMessages::new(vec![
97 pdu::ServerAudioOutputPdu::Training(pdu).into()
98 ]))
99 }
100
101 pub fn wave(&mut self, data: Vec<u8>, ts: u32) -> PduResult<RdpsndSvcMessages> {
102 let version = self.version()?;
103 let format_no = self
104 .format_no
105 .ok_or_else(|| pdu_other_err!("invalid state - no format"))?;
106
107 let msg = if version >= pdu::Version::V8 {
109 let pdu = pdu::Wave2Pdu {
110 block_no: self.block_no,
111 timestamp: 0,
112 audio_timestamp: ts,
113 format_no,
114 data: data.into(),
115 };
116 RdpsndSvcMessages::new(vec![pdu::ServerAudioOutputPdu::Wave2(pdu).into()])
117 } else {
118 let pdu = pdu::WavePdu {
119 block_no: self.block_no,
120 format_no,
121 timestamp: 0,
122 data: data.into(),
123 };
124 RdpsndSvcMessages::new(vec![pdu::ServerAudioOutputPdu::Wave(pdu).into()])
125 };
126
127 self.block_no = self.block_no.overflowing_add(1).0;
128
129 Ok(msg)
130 }
131
132 pub fn set_volume(&mut self, volume_left: u16, volume_right: u16) -> PduResult<RdpsndSvcMessages> {
133 if !self.flags()?.contains(pdu::AudioFormatFlags::VOLUME) {
134 return Err(pdu_other_err!("client doesn't support volume"));
135 }
136 let pdu = pdu::VolumePdu {
137 volume_left,
138 volume_right,
139 };
140 Ok(RdpsndSvcMessages::new(vec![
141 pdu::ServerAudioOutputPdu::Volume(pdu).into()
142 ]))
143 }
144
145 pub fn close(&mut self) -> PduResult<RdpsndSvcMessages> {
146 Ok(RdpsndSvcMessages::new(vec![pdu::ServerAudioOutputPdu::Close.into()]))
147 }
148}
149
150impl_as_any!(RdpsndServer);
151
152impl SvcProcessor for RdpsndServer {
153 fn channel_name(&self) -> ChannelName {
154 Self::NAME
155 }
156
157 fn compression_condition(&self) -> CompressionCondition {
158 CompressionCondition::Never
159 }
160
161 fn process(&mut self, payload: &[u8]) -> PduResult<Vec<SvcMessage>> {
162 let pdu = pdu::ClientAudioOutputPdu::decode(&mut ReadCursor::new(payload)).map_err(|e| decode_err!(e))?;
163 debug!(?pdu);
164 let msg = match self.state {
165 RdpsndState::WaitingForClientFormats => {
166 let pdu::ClientAudioOutputPdu::AudioFormat(af) = pdu else {
167 error!("Invalid PDU");
168 self.state = RdpsndState::Stop;
169 return Ok(vec![]);
170 };
171 self.client_format = Some(af);
172 if self.version()? >= pdu::Version::V6 {
173 self.state = RdpsndState::WaitingForQualityMode;
174 vec![]
175 } else {
176 self.state = RdpsndState::WaitingForTrainingConfirm;
177 self.training_pdu()?.into()
178 }
179 }
180 RdpsndState::WaitingForQualityMode => {
181 let pdu::ClientAudioOutputPdu::QualityMode(pdu) = pdu else {
182 error!("Invalid PDU");
183 self.state = RdpsndState::Stop;
184 return Ok(vec![]);
185 };
186 self.quality_mode = Some(pdu.quality_mode);
187 self.state = RdpsndState::WaitingForTrainingConfirm;
188 self.training_pdu()?.into()
189 }
190 RdpsndState::WaitingForTrainingConfirm => {
191 let pdu::ClientAudioOutputPdu::TrainingConfirm(_) = pdu else {
192 error!("Invalid PDU");
193 self.state = RdpsndState::Stop;
194 return Ok(vec![]);
195 };
196 let client_format = self.client_format.as_ref().expect("available in this state");
197 self.state = RdpsndState::Ready;
198 self.format_no = self.handler.start(client_format);
199 vec![]
200 }
201 RdpsndState::Ready => {
202 if let pdu::ClientAudioOutputPdu::WaveConfirm(c) = pdu {
203 debug!(?c);
204 }
205 vec![]
206 }
207 state => {
208 error!(?state, "Invalid state");
209 vec![]
210 }
211 };
212 Ok(msg)
213 }
214
215 fn start(&mut self) -> PduResult<Vec<SvcMessage>> {
216 if self.state != RdpsndState::Start {
217 error!("Attempted to start rdpsnd channel in invalid state");
218 }
219
220 let pdu = pdu::ServerAudioOutputPdu::AudioFormat(pdu::ServerAudioFormatPdu {
221 version: pdu::Version::V8,
222 formats: self.handler.get_formats().into(),
223 });
224
225 self.state = RdpsndState::WaitingForClientFormats;
226 Ok(vec![SvcMessage::from(pdu)])
227 }
228}
229
230impl Drop for RdpsndServer {
231 fn drop(&mut self) {
232 self.handler.stop();
233 }
234}
235
236impl SvcServerProcessor for RdpsndServer {}