dsf_core/service/
mod.rs

1//! This module provides a DSF Service implementation.
2//!
3//! `Publisher`, `Subscriber`, and `Net` traits provide functionality for publishing services,
4//! subscribing to services, and sending messages respectively.
5
6use crate::base::{Body, PrivateOptions};
7use crate::crypto;
8use crate::error::Error;
9use crate::options::Options;
10use crate::types::*;
11
12#[cfg(feature = "alloc")]
13use alloc::prelude::v1::*;
14
15pub mod kinds;
16
17// Service extensions
18pub mod publisher;
19pub use publisher::{DataOptions, Publisher, SecondaryOptions};
20
21pub mod subscriber;
22pub use subscriber::Subscriber;
23
24pub mod net;
25pub use net::Net;
26
27pub mod builder;
28pub use builder::ServiceBuilder;
29
30/// Generic Service Type.
31/// This provides the basis for all services in DSR.
32///
33/// Services should be constructed using the ServiceBuilder type
34#[derive(PartialEq, Debug, Clone)]
35#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
36#[cfg_attr(feature = "diesel", derive(diesel::Queryable))]
37pub struct Service {
38    id: Id,
39
40    application_id: u16,
41    kind: PageKind,
42
43    version: u16,
44    data_index: u16,
45
46    body: Body,
47
48    public_options: Vec<Options>,
49    private_options: PrivateOptions,
50
51    public_key: PublicKey,
52    private_key: Option<PrivateKey>,
53
54    encrypted: bool,
55    secret_key: Option<SecretKey>,
56
57    last_sig: Option<Signature>,
58}
59
60impl Default for Service {
61    /// Create a default / blank Service for further initialisation.
62    fn default() -> Service {
63        // Generate service key-pair
64        let (public_key, private_key) = crypto::new_pk().unwrap();
65
66        // Generate service ID from public key
67        let id = crypto::hash(&public_key).unwrap().into();
68
69        // Create service object
70        Service {
71            id,
72            application_id: 0,
73            kind: PageKind::Generic,
74            version: 0,
75            data_index: 0,
76            body: Body::None,
77            public_options: vec![],
78            private_options: PrivateOptions::None,
79            public_key,
80            private_key: Some(private_key),
81            encrypted: false,
82            secret_key: None,
83            last_sig: None,
84        }
85    }
86}
87
88impl Service {
89    pub fn id(&self) -> Id {
90        self.id.clone()
91    }
92
93    /// Update a service.
94    /// This allows in-place editing of descriptors and options and causes an update of the service version number
95    /// as well as a reset of the data_index.
96    pub fn update<U>(&mut self, update_fn: U) -> Result<(), Error>
97    where
98        U: Fn(&mut Body, &mut Vec<Options>, &mut PrivateOptions),
99    {
100        if self.private_key().is_none() {
101            return Err(Error::NoPrivateKey);
102        }
103
104        update_fn(
105            &mut self.body,
106            &mut self.public_options,
107            &mut self.private_options,
108        );
109
110        // Update service version
111        self.version += 1;
112
113        // Reset data index to 0;
114        self.data_index = 0;
115
116        Ok(())
117    }
118
119    pub fn is_origin(&self) -> bool {
120        match (&self.private_key, &self.encrypted, &self.secret_key) {
121            (Some(_), false, _) => true,
122            (Some(_), true, Some(_)) => true,
123            _ => false,
124        }
125    }
126
127    pub fn public_key(&self) -> PublicKey {
128        self.public_key.clone()
129    }
130
131    pub fn private_key(&self) -> Option<PrivateKey> {
132        self.private_key.clone()
133    }
134
135    pub fn secret_key(&self) -> Option<SecretKey> {
136        self.secret_key.clone()
137    }
138
139    pub fn set_private_key(&mut self, key: Option<PrivateKey>) {
140        self.private_key = key;
141    }
142
143    pub fn set_secret_key(&mut self, key: Option<SecretKey>) {
144        self.secret_key = key;
145    }
146}
147
148#[cfg(test)]
149mod test {
150
151    use core::convert::TryInto;
152    use std::net::{Ipv4Addr, SocketAddrV4};
153
154    use crate::base::Base;
155    use crate::page::Page;
156    use crate::service::publisher::{DataOptions, Publisher, SecondaryOptions};
157    use crate::service::subscriber::Subscriber;
158
159    use super::*;
160
161    #[test]
162    fn test_service() {
163        let socket = SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 8080);
164
165        println!("Creating new service");
166        let service_builder = ServiceBuilder::default()
167            .kind(PageKind::Generic.into())
168            .public_options(vec![Options::name("Test Service")])
169            .private_options(vec![Options::address_v4(socket)].into())
170            .encrypt();
171        let mut service = service_builder.build().unwrap();
172
173        println!("Generating and encoding service page");
174        let mut buff = vec![0u8; 1024];
175        let (n, mut page1) = service
176            .publish_primary(&mut buff)
177            .expect("Error creating page");
178
179        // Append sig to page1
180        //page1.set_signature(base1.signature().clone().unwrap());
181        assert_eq!(service.version, 0, "initial service version");
182
183        // Clear private data from encoded pages
184        page1.clean();
185
186        println!("Encoded service to {} bytes", n);
187
188        println!("Decoding service page");
189        let s = service.clone();
190        let pub_key = s.public_key();
191        let sec_key = s.secret_key();
192
193        let (base2, m) = Base::parse(
194            &buff[..n],
195            |_id| Some(pub_key.clone()),
196            |_id| sec_key.clone(),
197        )
198        .expect("Error parsing service page");
199        assert_eq!(n, m);
200        let mut page2: Page = base2
201            .try_into()
202            .expect("Error converting base message to page");
203        page2.raw = None;
204        assert_eq!(page1, page2);
205
206        println!("Generating service replica");
207        let mut replica = Service::load(&page2).expect("Error generating service replica");
208
209        println!("Updating service");
210        service
211            .update(|_body, public_options, _private_options| {
212                public_options.push(Options::kind("Test Kind"));
213            })
214            .expect("Error updating service");
215        assert_eq!(service.version, 1, "service.update updates service version");
216
217        println!("Generating updated page");
218        let (_n, page3) = service
219            .publish_primary(&mut buff)
220            .expect("Error publishing primary page");
221
222        println!("Applying updated page to replica");
223        replica
224            .apply_primary(&page3)
225            .expect("Error updating service replica");
226        assert_eq!(replica.version, 1);
227
228        println!("Generating a secondary page");
229        let secondary_options = SecondaryOptions::default();
230        let (_n, secondary) = service
231            .publish_secondary(&s.id(), secondary_options, &mut buff)
232            .expect("Error publishing secondary page");
233
234        println!("Validating secondary page");
235        service
236            .validate_secondary(&secondary)
237            .expect("Error validating secondary page against publisher");
238
239        println!("Generating a data object");
240        let data_options = DataOptions::default();
241        let (_n, data) = service
242            .publish_data(data_options, &mut buff)
243            .expect("Error publishing data object");
244
245        println!("Validating data object");
246        replica
247            .validate_data(&data)
248            .expect("Error validating data against replica");
249    }
250}