rainmaker_components/protocomm/
mod.rs1mod security;
15mod transports;
16
17use std::sync::Arc;
18use transports::{TransportGatt, TransportHttpd};
19use uuid::Uuid;
20
21pub use self::security::ProtocommSecurity;
22use self::security::SecurityTrait;
23use crate::http;
24
25#[allow(private_interfaces)]
36pub type ProtocommHttpd = Protocomm<TransportHttpd>;
37
38#[allow(private_interfaces)]
49pub type ProtocommGatt = Protocomm<TransportGatt>;
50
51#[derive(Default)]
52pub struct ProtocommGattConfig {
53 pub service_uuid: Uuid,
54}
55
56pub type ProtocommHttpdConfig = http::HttpConfiguration;
57
58#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
59pub(crate) enum EndpointType {
60 Version,
61 Security,
62 #[default]
63 Other,
64}
65
66pub type ProtocommCallbackType = Box<dyn Fn(&str, &[u8]) -> Vec<u8> + Send + Sync + 'static>;
67
68pub struct Protocomm<T> {
69 transport: T,
70 sec: Arc<ProtocommSecurity>,
71}
72
73impl Protocomm<TransportGatt> {
74 pub fn new(gatt_config: ProtocommGattConfig, security: ProtocommSecurity) -> Self {
75 let transport_ble = transports::TransportGatt::new(gatt_config.service_uuid);
76
77 Self {
78 transport: transport_ble,
79 sec: Arc::new(security),
80 }
81 }
82
83 pub fn set_version_info(&mut self, uuid: Uuid, ep_name: &str, version_info: String) {
84 self.transport.add_endpoint(
85 uuid,
86 ep_name,
87 Box::new(move |_ep, _data| version_info.as_bytes().to_vec()),
88 EndpointType::Version,
89 self.sec.clone(),
90 );
91 }
92
93 pub fn set_security_endpoint(&mut self, uuid: Uuid, ep_name: &str) {
94 self.transport.add_endpoint(
95 uuid,
96 ep_name,
97 Box::new(|_, _| Vec::default()),
98 EndpointType::Security,
99 self.sec.clone(),
100 );
101 }
102
103 pub fn register_endpoint(
104 &mut self,
105 uuid: Uuid,
106 ep_name: &str,
107 callback: ProtocommCallbackType,
108 ) {
109 log::debug!("Registering endpoint: {}", ep_name);
110 self.transport.add_endpoint(
111 uuid,
112 ep_name,
113 callback,
114 EndpointType::Other,
115 self.sec.clone(),
116 );
117 log::debug!("Registered endpoint: {}", ep_name);
118 }
119
120 pub fn start(&mut self) {
121 self.transport.start();
122 }
123}
124
125impl Protocomm<TransportHttpd> {
126 pub fn new(config: ProtocommHttpdConfig, security: ProtocommSecurity) -> Self {
127 let transport = TransportHttpd::new(config);
128 Self {
129 transport,
130 sec: Arc::new(security),
131 }
132 }
133
134 pub fn set_version_info(&mut self, ep_name: &str, version_info: String) {
135 self.register_endpoint_internal(
136 ep_name,
137 Box::new(move |_ep, _data| version_info.as_bytes().to_vec()),
138 EndpointType::Version,
139 );
140 }
141
142 pub fn set_security_endpoint(&mut self, ep_name: &str) {
143 self.register_endpoint_internal(ep_name, Box::new(|_, _| vec![]), EndpointType::Security);
144 }
145
146 pub fn register_endpoint(&mut self, ep_name: &str, callback: ProtocommCallbackType) {
147 self.register_endpoint_internal(ep_name, callback, EndpointType::Other);
148 }
149
150 fn register_endpoint_internal(
151 &mut self,
152 ep_name: &str,
153 cb: ProtocommCallbackType,
154 ep_type: EndpointType,
155 ) {
156 let sec = self.sec.clone();
157 self.transport.add_endpoint(ep_name, cb, ep_type, sec);
158 }
159}
160
161pub(crate) fn protocomm_req_handler(
162 ep: &str,
163 data: &[u8],
164 cb: &ProtocommCallbackType,
165 ep_type: &EndpointType,
166 sec: &Arc<ProtocommSecurity>,
167) -> Vec<u8> {
168 match ep_type {
169 EndpointType::Version => cb(ep, data),
170 EndpointType::Security => sec.security_handler(ep, data.to_vec()),
171 EndpointType::Other => {
172 let mut data = data.to_vec();
174
175 sec.decrypt(&mut data);
176 let mut res = cb(ep, &data);
177 sec.encrypt(&mut res);
178
179 res
180 }
181 }
182}