skyway_webrtc_gateway_api/data/
formats.rs

1use std::fmt;
2
3use serde::de::{self, Visitor};
4use serde::{Deserialize, Deserializer, Serialize};
5
6use crate::common::formats::{PhantomId, SerializableId, SocketInfo};
7use crate::error;
8use crate::prelude::{PeerId, Token};
9
10/// Query for POST /data/connections
11///
12/// It will send as JSON body
13///
14/// [API](http://35.200.46.204/#/2.data/data_connections_create)
15///
16#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
17pub struct ConnectQuery {
18    /// to identify which PeerObject calls to neighbour
19    pub peer_id: PeerId,
20    /// to show that this program has permission to control PeerObject
21    pub token: Token,
22    /// parameters for DataChannel
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub options: Option<ConnectQueryOption>,
25    /// connect to the neighbour which has this PeerId
26    pub target_id: PeerId,
27    /// Shows source Data Object which feeds data redirected to nighbour.
28    /// If this field is not set, DataConnection works as RecvOnly.
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub params: Option<DataIdWrapper>,
31    /// Shows destiation socket to which received data is redirected
32    /// If this field is not set, DataConnection works as SendOnly.
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub redirect_params: Option<SocketInfo<PhantomId>>,
35}
36
37/// Query parameter for POST /data/connections
38///
39/// Shows DataConnection parameters in SkyWay layer
40#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
41#[allow(non_snake_case)]
42pub struct ConnectQueryOption {
43    /// Metadata associated with the connection, passed in by whoever initiated the connection.
44    #[serde(skip_serializing_if = "Option::is_none")]
45    pub metadata: Option<String>,
46    /// Can be BINARY (default), BINARY_UTF8, JSON, or NONE.
47    #[serde(skip_serializing_if = "Option::is_none")]
48    pub serialization: Option<String>,
49    /// Detail option for DataConnection
50    #[serde(skip_serializing_if = "Option::is_none")]
51    pub dcInit: Option<DcInit>,
52}
53
54/// Query parameter for POST /data/connections
55///
56/// Shows DataConnection parameters in Browser layer.
57/// It's almost same as browser parameters.
58///
59/// [https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel](https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel)
60#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
61#[allow(non_snake_case)]
62pub struct DcInit {
63    /// Indicates whether or not the data channel guarantees in-order delivery of messages; the default is true, which indicates that the data channel is indeed ordered.
64    #[serde(skip_serializing_if = "Option::is_none")]
65    #[serde(default, deserialize_with = "crate::helper::deserialize_maybe_nan")]
66    pub ordered: Option<bool>,
67    /// The amount of time, in milliseconds, the browser is allowed to take to attempt to transmit a message.
68    #[serde(skip_serializing_if = "Option::is_none")]
69    #[serde(default, deserialize_with = "crate::helper::deserialize_maybe_nan")]
70    pub maxPacketLifeTime: Option<usize>,
71    /// The maximum number of times the WebRTC Gateway should try to retransmit a message before giving up.
72    #[serde(skip_serializing_if = "Option::is_none")]
73    #[serde(default, deserialize_with = "crate::helper::deserialize_maybe_nan")]
74    pub maxRetransmits: Option<usize>,
75    /// containing the name of the sub-protocol in use. If no protocol was specified when the data channel was created, then this property's value is "".
76    #[serde(skip_serializing_if = "Option::is_none")]
77    #[serde(default, deserialize_with = "crate::helper::deserialize_maybe_nan")]
78    pub protocol: Option<String>,
79    /// Indicates whether the RTCDataChannel's connection was negotiated by the Web app (true) or by the WebRTC layer (false).
80    #[serde(skip_serializing_if = "Option::is_none")]
81    #[serde(default, deserialize_with = "crate::helper::deserialize_maybe_nan")]
82    pub negotiated: Option<bool>,
83    /// ID number (between 0 and 65,534) which uniquely identifies the RTCDataChannel.
84    #[serde(skip_serializing_if = "Option::is_none")]
85    #[serde(default, deserialize_with = "crate::helper::deserialize_maybe_nan")]
86    pub id: Option<usize>,
87    /// Show priority of this channel.
88    #[serde(skip_serializing_if = "Option::is_none")]
89    #[serde(default, deserialize_with = "crate::helper::deserialize_maybe_nan")]
90    pub priority: Option<String>,
91}
92
93/// Identifier for source socket of data
94#[derive(Serialize, Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
95pub struct DataId(String);
96
97impl SerializableId for DataId {
98    fn try_create(data_id: impl Into<String>) -> Result<Self, error::Error>
99    where
100        Self: Sized,
101    {
102        // peer token's prefix is composed of a UUID and a prefix "pt-".
103        let data_id = data_id.into();
104        if !data_id.starts_with("da-") {
105            return Err(error::Error::create_local_error(
106                "token str\'s prefix is \"da-\"",
107            ));
108        }
109        if data_id.len() != 39 {
110            // It's length is 39(UUID: 36 + prefix: 3).
111            return Err(error::Error::create_local_error(
112                "token str's length should be 39",
113            ));
114        }
115        if !data_id.is_ascii() {
116            return Err(error::Error::create_local_error(
117                "token str should be ascii",
118            ));
119        }
120
121        Ok(DataId(data_id))
122    }
123
124    fn as_str(&self) -> &str {
125        self.0.as_str()
126    }
127
128    fn id(&self) -> String {
129        self.0.clone()
130    }
131
132    fn key(&self) -> &'static str {
133        "data_id"
134    }
135}
136
137struct DataVisitor;
138
139impl<'de> Visitor<'de> for DataVisitor {
140    type Value = DataId;
141
142    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
143        formatter.write_str("a 39 length str")
144    }
145
146    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
147    where
148        E: de::Error,
149    {
150        let data_id = DataId::try_create(value);
151        if let Err(error::Error::LocalError(err)) = data_id {
152            return Err(E::custom(format!("fail to deserialize DataId: {}", err)));
153        } else if let Err(_) = data_id {
154            return Err(E::custom(format!("fail to deserialize DataId")));
155        }
156
157        Ok(data_id.unwrap())
158    }
159
160    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
161    where
162        E: de::Error,
163    {
164        let data_id = DataId::try_create(value);
165        if let Err(error::Error::LocalError(err)) = data_id {
166            return Err(E::custom(format!("fail to deserialize Token: {}", err)));
167        } else if let Err(_) = data_id {
168            return Err(E::custom(format!("fail to deserialize Token")));
169        }
170
171        Ok(data_id.unwrap())
172    }
173}
174
175impl<'de> Deserialize<'de> for DataId {
176    fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
177    where
178        D: Deserializer<'de>,
179    {
180        deserializer.deserialize_identifier(DataVisitor)
181    }
182}
183
184/// Struct just for adapter to adjust JSON format
185#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
186pub struct DataIdWrapper {
187    pub data_id: DataId,
188}
189
190/// Identifier for DataConnection
191#[derive(Serialize, Debug, Clone, PartialOrd, PartialEq, Eq, Ord, Hash)]
192pub struct DataConnectionId(String);
193
194impl DataConnectionId {
195    pub fn as_str(&self) -> &str {
196        self.0.as_str()
197    }
198
199    pub fn try_create(data_connection_id: impl Into<String>) -> Result<Self, error::Error>
200    where
201        Self: Sized,
202    {
203        // peer token's prefix is composed of a UUID and a prefix "pt-".
204        let data_connection_id = data_connection_id.into();
205        if !data_connection_id.starts_with("dc-") {
206            return Err(error::Error::create_local_error(
207                "data_connection_id\'s prefix is \"dc-\"",
208            ));
209        }
210        if data_connection_id.len() != 39 {
211            // It's length is 39(UUID: 36 + prefix: 3).
212            return Err(error::Error::create_local_error(
213                "token str's length should be 39",
214            ));
215        }
216        if !data_connection_id.is_ascii() {
217            return Err(error::Error::create_local_error(
218                "token str should be ascii",
219            ));
220        }
221
222        Ok(DataConnectionId(data_connection_id))
223    }
224}
225
226struct DataConnectionIdVisitor;
227
228impl<'de> Visitor<'de> for DataConnectionIdVisitor {
229    type Value = DataConnectionId;
230
231    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
232        formatter.write_str("a 39 length str")
233    }
234
235    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
236    where
237        E: de::Error,
238    {
239        let data_connection_id = DataConnectionId::try_create(value);
240        if let Err(error::Error::LocalError(err)) = data_connection_id {
241            return Err(E::custom(format!("fail to deserialize DataId: {}", err)));
242        } else if let Err(_) = data_connection_id {
243            return Err(E::custom(format!("fail to deserialize DataId")));
244        }
245
246        Ok(data_connection_id.unwrap())
247    }
248
249    fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
250    where
251        E: de::Error,
252    {
253        let data_connection_id = DataConnectionId::try_create(value);
254        if let Err(error::Error::LocalError(err)) = data_connection_id {
255            return Err(E::custom(format!("fail to deserialize Token: {}", err)));
256        } else if let Err(_) = data_connection_id {
257            return Err(E::custom(format!("fail to deserialize Token")));
258        }
259
260        Ok(data_connection_id.unwrap())
261    }
262}
263
264impl<'de> Deserialize<'de> for DataConnectionId {
265    fn deserialize<D>(deserializer: D) -> Result<Self, <D as Deserializer<'de>>::Error>
266    where
267        D: Deserializer<'de>,
268    {
269        deserializer.deserialize_identifier(DataConnectionIdVisitor)
270    }
271}
272
273/// Response JSON from POST /data/connections
274///
275/// [API](http://35.200.46.204/#/2.data/data_connections_create)
276///
277#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
278pub struct ConnectionResponse {
279    /// Fixed value as `"PEERS_CONNECT"`
280    pub command_type: String,
281    /// Id to identify this DataConnection
282    pub params: DataConnectionIdWrapper,
283}
284
285/// Struct just for adapter to adjust JSON format
286#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
287pub struct DataConnectionIdWrapper {
288    pub data_connection_id: DataConnectionId,
289}
290
291/// Query for PUT /data/connections
292///
293/// It will send as JSON body
294///
295/// [API](http://35.200.46.204/#/2.data/data_connection_put)
296///
297#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
298pub struct RedirectDataParams {
299    /// Data source for the DataConnection
300    #[serde(skip_serializing_if = "Option::is_none")]
301    pub feed_params: Option<DataIdWrapper>,
302    /// Data destination for the DataConnection. A WebRTC Gateway will redirect received data to this socket.
303    #[serde(skip_serializing_if = "Option::is_none")]
304    pub redirect_params: Option<SocketInfo<PhantomId>>,
305}
306
307/// Response from PUT /data/connections
308///
309/// It will send as JSON body
310///
311/// [API](http://35.200.46.204/#/2.data/data_connection_put)
312///
313#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
314pub struct RedirectDataResponse {
315    /// Fixed value as `"DATA_CONNECTION_PUT"`
316    pub command_type: String,
317    /// Identify which data will be redirected.
318    pub data_id: DataId,
319}
320
321/// Response from GET /data/connections/{data_cnnection_id}/status
322///
323/// [API](http://35.200.46.204/#/2.data/data_connection_status)
324#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
325pub struct DataConnectionStatus {
326    /// Identifies a peer connected with this DataConnection
327    pub remote_id: String,
328    /// Shows size of buffer
329    pub buffersize: usize,
330    /// The optional label passed in or assigned by SkyWay when the connection was initiated.
331    pub label: String,
332    /// Any type of metadata associated with the connection, passed in by whoever initiated the connection.
333    pub metadata: String,
334    /// This is true if the connection is open and ready for read/write.
335    pub open: bool,
336    /// Whether the underlying data channels are reliable; defined when the connection was initiated.
337    pub reliable: bool,
338    /// The serialization format of the data sent over the connection. Can be BINARY (default), BINARY_UTF8, JSON, or NONE.
339    pub serialization: String,
340    /// Fixed value as `"data"`
341    pub r#type: String,
342}
343
344#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
345#[serde(tag = "event")]
346pub(crate) enum EventEnum {
347    OPEN,
348    CLOSE,
349    ERROR { error_message: String },
350    TIMEOUT,
351}