pub fn send_encrypted_message(&self, client: &HyperClient,
                                  data: &GenericMessage,
                                  storage: Arc<StorageManager>,
                                  devices: Arc<Mutex<Devices>>)
        -> BerylliumFuture<()>
    {
        let bytes = future_try!(data.write_to_bytes());
        let mut devices_clone = {
            let devs = devices.lock();
            devs.missing.clone()    // clone and release the lock
        };

        let f = {
            let encrypted = storage.encrypt_for_devices(&bytes, &devices_clone);
            let msg = MessageRequest {
                sender: &self.client_id,
                recipients: encrypted,
            };

            self.send_message(&client, msg, false)
        };

        let bot_client = self.clone();
        let hyper_client = client.clone();

        let f = f.and_then(move |stat| match stat {
            MessageStatus::Sent =>
                Box::new(future::ok(())) as BerylliumFuture<()>,
            MessageStatus::Failed(devs) => {
                info!("Getting prekeys for missing devices...");
                let f = bot_client.get_prekeys(&hyper_client, &devs.missing);
                let f = f.and_then(move |keys| {
                    let mut new_data = HashMap::with_capacity(keys.len());
                    for (user_id, clients) in &keys {
                        for (client_id, prekey) in clients {
                            let prekey = future_try_box!(base64::decode(&prekey.key));
                            let clients = new_data.entry(user_id.as_str())
                                                  .or_insert(HashMap::new());
                            let res = storage.encrypt(user_id.as_str(), client_id,
                                                      &bytes, &prekey);
                            let encrypted = future_try_box!(res);
                            clients.entry(client_id.as_str()).or_insert(encrypted);

                            // We've successfully encrypted the message for a new device
                            // with a new prekey. Since we've already stored the session,
                            // we can safely update our devices.
                            let clients = devices_clone.entry(user_id.clone())
                                                       .or_insert(vec![]);
                            clients.push(client_id.to_owned());
                        }
                    }

                    devices.lock().missing = devices_clone;
                    let message = MessageRequest {
                        sender: &bot_client.client_id,
                        recipients: new_data,
                    };

                    let f = bot_client.send_message(&hyper_client, message, false);
                    let f = f.and_then(move |stat| {
                        match stat {
                            MessageStatus::Sent => future::ok(()),
                            MessageStatus::Failed(_) => {
                                let msg = "Cannot send message! Failed after device check";
                                future::err(BerylliumError::Other(String::from(msg)))
                            },
                        }
                    });

                    Box::new(f) as BerylliumFuture<()>
                });

                Box::new(f)
            },
        });

        Box::new(f)
    }
/// Used to send all messages encrypted with the appropriate device prekeys.
Used to send all messages encrypted with the appropriate device prekeys.
Used to send all messages encrypted with the appropriate device prekeys .
pub fn send_encrypted_message(&self, client: &HyperClient,
                                  data: &GenericMessage,
                                  storage: Arc<StorageManager>,
                                  devices: Arc<Mutex<Devices>>)
        -> BerylliumFuture<()>
    {
        let bytes = future_try!(data.write_to_bytes());
        let mut devices_clone = {
            let devs = devices.lock();
            devs.missing.clone()    // clone and release the lock
        };
        let f = {
            let encrypted = storage.encrypt_for_devices(&bytes, &devices_clone);
            let msg = MessageRequest {
                sender: &self.client_id,
                recipients: encrypted,
            };
            self.send_message(&client, msg, false)
        };
        let bot_client = self.clone();
        let hyper_client = client.clone();
        let f = f.and_then(move |stat| match stat {
            MessageStatus::Sent =>
                Box::new(future::ok(())) as BerylliumFuture<()>,
            MessageStatus::Failed(devs) => {
                info!("Getting prekeys for missing devices...");
                let f = bot_client.get_prekeys(&hyper_client, &devs.missing);
                let f = f.and_then(move |keys| {
                    let mut new_data = HashMap::with_capacity(keys.len());
                    for (user_id, clients) in &keys {
                        for (client_id, prekey) in clients {
                            let prekey = future_try_box!(base64::decode(&prekey.key));
                            let clients = new_data.entry(user_id.as_str())
                                                  .or_insert(HashMap::new());
                            let res = storage.encrypt(user_id.as_str(), client_id,
                                                      &bytes, &prekey);
                            let encrypted = future_try_box!(res);
                            clients.entry(client_id.as_str()).or_insert(encrypted);
                            // We've successfully encrypted the message for a new device
                            // with a new prekey. Since we've already stored the session,
                            // we can safely update our devices.
                            let clients = devices_clone.entry(user_id.clone())
                                                       .or_insert(vec![]);
                            clients.push(client_id.to_owned());
                        }
                    }
                    devices.lock().missing = devices_clone;
                    let message = MessageRequest {
                        sender: &bot_client.client_id,
                        recipients: new_data,
                    };
                    let f = bot_client.send_message(&hyper_client, message, false);
                    let f = f.and_then(move |stat| {
                        match stat {
                            MessageStatus::Sent => future::ok(()),
                            MessageStatus::Failed(_) => {
                                let msg = "Cannot send message! Failed after device check";
                                future::err(BerylliumError::Other(String::from(msg)))
                            },
                        }
                    });
                    Box::new(f) as BerylliumFuture<()>
                });
                Box::new(f)
            },
        });
        Box::new(f)
    }
pub fn send_encrypted_message ( & self , client : & HyperClient , data : & GenericMessage , storage : Arc < StorageManager > , devices : Arc < Mutex < Devices > > ) -> BerylliumFuture < ( ) > { let bytes = future_try ! ( data write_to_bytes ( ) ) ; let mut devices_clone = { let devs = devices . lock ( ) ; devs . missing . clone ( ) // clone and release the lock } ; let f = { let encrypted = storage . encrypt_for_devices ( & bytes , & devices_clone ) ; let msg = MessageRequest { sender : & self . client_id , recipients : encrypted , } ; self . send_message ( & client , msg , false ) } ; let bot_client = self . clone ( ) ; let hyper_client = client . clone ( ) ; let f = f . and_then ( move | stat | match stat { MessageStatus :: Sent => Box :: new ( future :: ok ( ( ) ) ) as BerylliumFuture < ( ) > , MessageStatus :: Failed ( devs ) => { info ! ( " " ) ; let f = bot_client . get_prekeys ( & hyper_client , & devs . missing ) ; let f = f . and_then ( move | keys | { let mut new_data = HashMap :: with_capacity ( keys . len ( ) ) ; for ( user_id , clients ) in & keys { for ( client_id , prekey ) in clients { let prekey = future_try_box ! ( base64 decode ( prekey key ) ) ; let clients = new_data . entry ( user_id . as_str ( ) ) . or_insert ( HashMap :: new ( ) ) ; let res = storage . encrypt ( user_id . as_str ( ) , client_id , & bytes , & prekey ) ; let encrypted = future_try_box ! ( res ) ; clients . entry ( client_id . as_str ( ) ) . or_insert ( encrypted ) ; // We've successfully encrypted the message for a new device // with a new prekey. Since we've already stored the session, // we can safely update our devices. let clients = devices_clone . entry ( user_id . clone ( ) ) . or_insert ( vec ! [ ] ) ; clients . push ( client_id . to_owned ( ) ) ; } } devices . lock ( ) . missing = devices_clone ; let message = MessageRequest { sender : & bot_client . client_id , recipients : new_data , } ; let f = bot_client . send_message ( & hyper_client , message , false ) ; let f = f . and_then ( move | stat | { match stat { MessageStatus :: Sent => future :: ok ( ( ) ) , MessageStatus :: Failed ( _ ) => { let msg = " " ; future :: err ( BerylliumError :: Other ( String :: from ( msg ) ) ) } , } } ) ; Box :: new ( f ) as BerylliumFuture < ( ) > } ) ; Box :: new ( f ) } , } ) ; Box :: new ( f ) }
Used to send all messages encrypted with the appropriate device prekeys.
Used to send all messages encrypted with the appropriate device prekeys .
&self
client
&HyperClient
data
&GenericMessage
storage
Arc<StorageManager>
devices
Arc<Mutex<Devices>>