sccp_protocol/message/codec/
conference.rs1use super::*;
4
5pub(super) const MAX_CONFERENCE_PASSTHROUGH_DATA: usize = 2000;
6pub(super) const MAX_AUDIT_CONFERENCE_ENTRIES: usize = 32;
7pub(super) const MAX_AUDIT_PARTICIPANT_DATA: usize = 256;
8
9pub(super) fn encode_participant_request(
10 message_id: u32,
11 conference_id: crate::types::ConferenceId,
12 participant: &ConferenceParticipant,
13) -> Result<WireParticipantRequest, CodecError> {
14 Ok(WireParticipantRequest {
15 conference_id: conference_id.get(),
16 call_reference: participant.call_reference.get(),
17 presentation_restrictions: participant.presentation_restrictions.bits(),
18 participant_name: WireFixedText::new(message_id, "participant name", &participant.name)?,
19 participant_number: WireFixedText::new(
20 message_id,
21 "participant number",
22 &participant.number,
23 )?,
24 conference_name: WireFixedText::new(
25 message_id,
26 "conference name",
27 &participant.conference_name,
28 )?,
29 })
30}
31
32pub(super) fn decode_participant_request(
33 payload: &[u8],
34 message_id: u32,
35) -> Result<(crate::types::ConferenceId, ConferenceParticipant), CodecError> {
36 validate_exact_payload(payload, message_id, 108)?;
37 let value: WireParticipantRequest = decode(message_id, payload)?;
38 Ok((
39 value.conference_id.into(),
40 ConferenceParticipant {
41 call_reference: value.call_reference.into(),
42 presentation_restrictions: PartyInformationRestrictions::from_bits_retain(
43 value.presentation_restrictions,
44 ),
45 name: value.participant_name.text()?,
46 number: value.participant_number.text()?,
47 conference_name: value.conference_name.text()?,
48 },
49 ))
50}
51
52impl ConferenceParticipantChange {
53 pub fn to_user_data_v1(
56 &self,
57 routing: ParticipantChangeRouting,
58 ) -> Result<UserDataV1Message, CodecError> {
59 let data = encode(
60 wire_id::USER_TO_DEVICE_DATA_V1,
61 &encode_participant_request(
62 wire_id::USER_TO_DEVICE_DATA_V1,
63 self.conference_id,
64 &self.participant,
65 )?,
66 )?;
67 Ok(UserDataV1Message {
68 application_id: routing.application_id.get(),
69 line_instance: routing.line_instance,
70 call_reference: self.participant.call_reference.get(),
71 transaction_id: routing.transaction_id.get(),
72 sequence_flag: routing.sequence_flag,
73 display_priority: routing.display_priority,
74 conference_id: self.conference_id.get(),
75 application_instance_id: routing.application_instance_id.get(),
76 routing: routing.routing,
77 data,
78 })
79 }
80
81 pub fn from_user_data_v1(message: &UserDataV1Message) -> Result<Self, CodecError> {
84 let (conference_id, participant) =
85 decode_participant_request(&message.data, wire_id::USER_TO_DEVICE_DATA_V1)?;
86 if message.conference_id != conference_id.get() {
87 return Err(CodecError::InvalidValue {
88 message_id: wire_id::USER_TO_DEVICE_DATA_V1,
89 field: "participant change conference ID",
90 value: u64::from(message.conference_id),
91 });
92 }
93 if message.call_reference != participant.call_reference.get() {
94 return Err(CodecError::InvalidValue {
95 message_id: wire_id::USER_TO_DEVICE_DATA_V1,
96 field: "participant change call reference",
97 value: u64::from(message.call_reference),
98 });
99 }
100 Ok(Self {
101 conference_id,
102 participant,
103 })
104 }
105}
106
107pub(super) fn validate_conference_data_length(
108 payload: &[u8],
109 message_id: u32,
110 header_size: usize,
111 length_offset: usize,
112) -> Result<(), CodecError> {
113 if payload.len() < header_size {
114 return Err(CodecError::Truncated {
115 message_id,
116 needed: header_size,
117 actual: payload.len(),
118 });
119 }
120 let data_length = usize_from_wire(
121 message_id,
122 "conference passthrough data",
123 u32::from_le_bytes(
124 payload[length_offset..length_offset + 4]
125 .try_into()
126 .expect("validated conference header contains length word"),
127 ),
128 )?;
129 if data_length > MAX_CONFERENCE_PASSTHROUGH_DATA {
130 return Err(CodecError::CountTooLarge {
131 message_id,
132 field: "conference passthrough data",
133 count: data_length,
134 maximum: MAX_CONFERENCE_PASSTHROUGH_DATA,
135 });
136 }
137 let needed = header_size + data_length;
138 if payload.len() < needed {
139 return Err(CodecError::Truncated {
140 message_id,
141 needed,
142 actual: payload.len(),
143 });
144 }
145 Ok(())
146}
147
148pub(super) fn validate_conference_data_for_encode(
149 message_id: u32,
150 passthrough_data: &[u8],
151) -> Result<u32, CodecError> {
152 if passthrough_data.len() > MAX_CONFERENCE_PASSTHROUGH_DATA {
153 return Err(CodecError::CountTooLarge {
154 message_id,
155 field: "conference passthrough data",
156 count: passthrough_data.len(),
157 maximum: MAX_CONFERENCE_PASSTHROUGH_DATA,
158 });
159 }
160 wire_count(
161 message_id,
162 "conference passthrough data",
163 passthrough_data.len(),
164 )
165}