1use crate::tlv;
7use anyhow;
8use serde_json;
9
10
11use crate::clusters::helpers::{serialize_opt_bytes_as_hex};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
17#[repr(u8)]
18pub enum StatusCode {
19 Endpointalreadyinstalled = 2,
21 Rootcertificatenotfound = 3,
23 Clientcertificatenotfound = 4,
25 Endpointinuse = 5,
27 Invalidtime = 6,
29}
30
31impl StatusCode {
32 pub fn from_u8(value: u8) -> Option<Self> {
34 match value {
35 2 => Some(StatusCode::Endpointalreadyinstalled),
36 3 => Some(StatusCode::Rootcertificatenotfound),
37 4 => Some(StatusCode::Clientcertificatenotfound),
38 5 => Some(StatusCode::Endpointinuse),
39 6 => Some(StatusCode::Invalidtime),
40 _ => None,
41 }
42 }
43
44 pub fn to_u8(self) -> u8 {
46 self as u8
47 }
48}
49
50impl From<StatusCode> for u8 {
51 fn from(val: StatusCode) -> Self {
52 val as u8
53 }
54}
55
56#[derive(Debug, serde::Serialize)]
59pub struct TLSEndpoint {
60 pub endpoint_id: Option<u8>,
61 #[serde(serialize_with = "serialize_opt_bytes_as_hex")]
62 pub hostname: Option<Vec<u8>>,
63 pub port: Option<u16>,
64 pub caid: Option<u8>,
65 pub ccdid: Option<u8>,
66 pub reference_count: Option<u8>,
67}
68
69pub fn encode_provision_endpoint(hostname: Vec<u8>, port: u16, caid: u8, ccdid: Option<u8>, endpoint_id: Option<u8>) -> anyhow::Result<Vec<u8>> {
73 let tlv = tlv::TlvItemEnc {
74 tag: 0,
75 value: tlv::TlvItemValueEnc::StructInvisible(vec![
76 (0, tlv::TlvItemValueEnc::OctetString(hostname)).into(),
77 (1, tlv::TlvItemValueEnc::UInt16(port)).into(),
78 (2, tlv::TlvItemValueEnc::UInt8(caid)).into(),
79 (3, tlv::TlvItemValueEnc::UInt8(ccdid.unwrap_or(0))).into(),
80 (4, tlv::TlvItemValueEnc::UInt8(endpoint_id.unwrap_or(0))).into(),
81 ]),
82 };
83 Ok(tlv.encode()?)
84}
85
86pub fn encode_find_endpoint(endpoint_id: u8) -> anyhow::Result<Vec<u8>> {
88 let tlv = tlv::TlvItemEnc {
89 tag: 0,
90 value: tlv::TlvItemValueEnc::StructInvisible(vec![
91 (0, tlv::TlvItemValueEnc::UInt8(endpoint_id)).into(),
92 ]),
93 };
94 Ok(tlv.encode()?)
95}
96
97pub fn encode_remove_endpoint(endpoint_id: u8) -> anyhow::Result<Vec<u8>> {
99 let tlv = tlv::TlvItemEnc {
100 tag: 0,
101 value: tlv::TlvItemValueEnc::StructInvisible(vec![
102 (0, tlv::TlvItemValueEnc::UInt8(endpoint_id)).into(),
103 ]),
104 };
105 Ok(tlv.encode()?)
106}
107
108pub fn decode_max_provisioned(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
112 if let tlv::TlvItemValue::Int(v) = inp {
113 Ok(*v as u8)
114 } else {
115 Err(anyhow::anyhow!("Expected UInt8"))
116 }
117}
118
119pub fn decode_provisioned_endpoints(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<TLSEndpoint>> {
121 let mut res = Vec::new();
122 if let tlv::TlvItemValue::List(v) = inp {
123 for item in v {
124 res.push(TLSEndpoint {
125 endpoint_id: item.get_int(&[0]).map(|v| v as u8),
126 hostname: item.get_octet_string_owned(&[1]),
127 port: item.get_int(&[2]).map(|v| v as u16),
128 caid: item.get_int(&[3]).map(|v| v as u8),
129 ccdid: item.get_int(&[4]).map(|v| v as u8),
130 reference_count: item.get_int(&[5]).map(|v| v as u8),
131 });
132 }
133 }
134 Ok(res)
135}
136
137
138pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
150 if cluster_id != 0x0802 {
152 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0802, got {}\"}}", cluster_id);
153 }
154
155 match attribute_id {
156 0x0000 => {
157 match decode_max_provisioned(tlv_value) {
158 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
159 Err(e) => format!("{{\"error\": \"{}\"}}", e),
160 }
161 }
162 0x0001 => {
163 match decode_provisioned_endpoints(tlv_value) {
164 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
165 Err(e) => format!("{{\"error\": \"{}\"}}", e),
166 }
167 }
168 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
169 }
170}
171
172pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
177 vec![
178 (0x0000, "MaxProvisioned"),
179 (0x0001, "ProvisionedEndpoints"),
180 ]
181}
182
183#[derive(Debug, serde::Serialize)]
184pub struct ProvisionEndpointResponse {
185 pub endpoint_id: Option<u8>,
186}
187
188#[derive(Debug, serde::Serialize)]
189pub struct FindEndpointResponse {
190 pub endpoint: Option<TLSEndpoint>,
191}
192
193pub fn decode_provision_endpoint_response(inp: &tlv::TlvItemValue) -> anyhow::Result<ProvisionEndpointResponse> {
197 if let tlv::TlvItemValue::List(_fields) = inp {
198 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
199 Ok(ProvisionEndpointResponse {
200 endpoint_id: item.get_int(&[0]).map(|v| v as u8),
201 })
202 } else {
203 Err(anyhow::anyhow!("Expected struct fields"))
204 }
205}
206
207pub fn decode_find_endpoint_response(inp: &tlv::TlvItemValue) -> anyhow::Result<FindEndpointResponse> {
209 if let tlv::TlvItemValue::List(_fields) = inp {
210 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
211 Ok(FindEndpointResponse {
212 endpoint: {
213 if let Some(nested_tlv) = item.get(&[0]) {
214 if let tlv::TlvItemValue::List(_) = nested_tlv {
215 let nested_item = tlv::TlvItem { tag: 0, value: nested_tlv.clone() };
216 Some(TLSEndpoint {
217 endpoint_id: nested_item.get_int(&[0]).map(|v| v as u8),
218 hostname: nested_item.get_octet_string_owned(&[1]),
219 port: nested_item.get_int(&[2]).map(|v| v as u16),
220 caid: nested_item.get_int(&[3]).map(|v| v as u8),
221 ccdid: nested_item.get_int(&[4]).map(|v| v as u8),
222 reference_count: nested_item.get_int(&[5]).map(|v| v as u8),
223 })
224 } else {
225 None
226 }
227 } else {
228 None
229 }
230 },
231 })
232 } else {
233 Err(anyhow::anyhow!("Expected struct fields"))
234 }
235}
236