Skip to main content

metaverse_core/
capabilities.rs

1use crate::errors::CapabilityError;
2
3use super::session::Mailbox;
4use actix::{AsyncContext, Handler, Message, WrapFuture};
5use log::error;
6use metaverse_messages::http::capabilities::{Capability, CapabilityRequest};
7use std::collections::HashMap;
8
9/// Message to update the capability urls
10///
11/// # Cause
12/// [`SendCapabilityRequest`]
13#[derive(Debug, Message)]
14#[rtype(result = "()")]
15pub struct SetCapabilityUrls {
16    capability_urls: HashMap<Capability, String>,
17}
18
19/// Message to request full capability urls from the esrver
20///
21/// # Cause
22/// - Successful login, from the handle_login function in session.rs
23///
24/// # Effect
25/// - Seed capability URL HTTP post
26/// - [`SetCapabilityUrls`] if the post was successful
27#[derive(Debug, Message)]
28#[rtype(result = "()")]
29pub struct SendCapabilityRequest {
30    /// The capabilities requested
31    pub capability_request: CapabilityRequest,
32}
33
34impl Handler<SetCapabilityUrls> for Mailbox {
35    type Result = ();
36    fn handle(&mut self, msg: SetCapabilityUrls, _: &mut Self::Context) -> Self::Result {
37        if let Some(session) = &mut self.session {
38            session.capability_urls.extend(msg.capability_urls);
39        }
40    }
41}
42
43impl Handler<SendCapabilityRequest> for Mailbox {
44    type Result = ();
45    fn handle(&mut self, msg: SendCapabilityRequest, ctx: &mut Self::Context) -> Self::Result {
46        if let Some(session) = &self.session {
47            let seed_capability_url = session.seed_capability_url.clone();
48            let address = ctx.address().clone();
49            let caps = msg.capability_request.capabilities;
50            ctx.spawn(
51                async move {
52                    match send_cap_request(seed_capability_url, caps).await {
53                        Ok(capability_urls) => {
54                            address.do_send(SetCapabilityUrls { capability_urls });
55                        }
56                        Err(e) => {
57                            error!("{:?}", e)
58                        }
59                    }
60                }
61                .into_actor(self),
62            );
63        }
64    }
65}
66
67async fn send_cap_request(
68    seed_capability_url: String,
69    capabilities: String,
70) -> Result<HashMap<Capability, String>, CapabilityError> {
71    let client = awc::Client::default();
72    let body = client
73        .post(seed_capability_url)
74        .insert_header(("Content-Type", "application/llsd+xml"))
75        .send_body(capabilities)
76        .await?
77        .body()
78        .await?;
79    Ok(CapabilityRequest::response_from_llsd(&body)?)
80}