From 04eee089e0c40fd61e16e130562ad2409b316cd3 Mon Sep 17 00:00:00 2001 From: Timo Date: Fri, 14 Aug 2020 11:31:31 +0200 Subject: [PATCH] feat: first steps towards joining rooms over federation --- Cargo.lock | 27 ++++--- Cargo.toml | 6 +- src/client_server/alias.rs | 23 ++++-- src/client_server/directory.rs | 79 +++++++++++------- src/client_server/membership.rs | 124 +++++++++++++++++++++++----- src/client_server/room.rs | 15 ++-- src/error.rs | 7 ++ src/lib.rs | 1 + src/main.rs | 14 ++-- src/server_server.rs | 138 +++++++++++++++++--------------- 10 files changed, 291 insertions(+), 143 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 014c5cc6..1166304e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -267,6 +267,7 @@ checksum = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd" name = "conduit" version = "0.1.0" dependencies = [ + "base64 0.12.3", "directories", "http", "image", @@ -1559,7 +1560,7 @@ dependencies = [ [[package]] name = "ruma" version = "0.0.1" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "ruma-api", "ruma-client-api", @@ -1573,7 +1574,7 @@ dependencies = [ [[package]] name = "ruma-api" version = "0.17.0-alpha.1" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "http", "percent-encoding", @@ -1588,7 +1589,7 @@ dependencies = [ [[package]] name = "ruma-api-macros" version = "0.17.0-alpha.1" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1599,7 +1600,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.10.0-alpha.1" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "assign", "http", @@ -1617,7 +1618,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.2.0" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "js_int", "ruma-identifiers", @@ -1630,7 +1631,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.22.0-alpha.1" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "js_int", "ruma-common", @@ -1645,7 +1646,7 @@ dependencies = [ [[package]] name = "ruma-events-macros" version = "0.22.0-alpha.1" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1656,7 +1657,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.0.3" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "js_int", "ruma-api", @@ -1671,7 +1672,7 @@ dependencies = [ [[package]] name = "ruma-identifiers" version = "0.17.4" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "rand", "ruma-identifiers-macros", @@ -1683,7 +1684,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-macros" version = "0.17.4" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "proc-macro2", "quote", @@ -1694,7 +1695,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.1.1" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "ruma-serde", "serde", @@ -1705,7 +1706,7 @@ dependencies = [ [[package]] name = "ruma-serde" version = "0.2.3" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "form_urlencoded", "itoa", @@ -1717,7 +1718,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.6.0-dev.1" -source = "git+https://github.com/ruma/ruma?rev=987d48666cf166cf12100b5dbc61b5e3385c4014#987d48666cf166cf12100b5dbc61b5e3385c4014" +source = "git+https://github.com/timokoesters/ruma?branch=timo-fixes#8868d2f72bc5d54f04154fb4fe71b08e4f69a0ae" dependencies = [ "base64 0.12.3", "ring", diff --git a/Cargo.toml b/Cargo.toml index 90633ded..4945e3c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,9 +16,10 @@ edition = "2018" #rocket = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "8d779caa22c63b15a6c3ceb75d8f6d4971b2eb67", features = ["tls"] } # Used to handle requests rocket = { git = "https://github.com/timokoesters/Rocket.git", branch = "empty_parameters", features = ["tls"] } -tokio = "0.2.22" # Used for long polling -ruma = { git = "https://github.com/ruma/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"], rev = "987d48666cf166cf12100b5dbc61b5e3385c4014" } # Used for matrix spec type definitions and helpers +#ruma = { git = "https://github.com/ruma/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"], rev = "987d48666cf166cf12100b5dbc61b5e3385c4014" } # Used for matrix spec type definitions and helpers +ruma = { git = "https://github.com/timokoesters/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"], branch = "timo-fixes" } # Used for matrix spec type definitions and helpers #ruma = { path = "../ruma/ruma", features = ["rand", "client-api", "federation-api", "unstable-pre-spec", "unstable-synapse-quirks"] } +tokio = "0.2.22" # Used for long polling sled = "0.32.0" # Used for storing data permanently log = "0.4.8" # Used for emitting log entries http = "0.2.1" # Used for rocket<->ruma conversions @@ -31,6 +32,7 @@ rust-argon2 = "0.8.2" # Used to hash passwords reqwest = "0.10.6" # Used to send requests thiserror = "1.0.19" # Used for conduit::Error type image = { version = "0.23.4", default-features = false, features = ["jpeg", "png", "gif"] } # Used to generate thumbnails for images +base64 = "0.12.3" # Used to encode server public key [features] default = ["conduit_bin"] diff --git a/src/client_server/alias.rs b/src/client_server/alias.rs index 087221bc..848b9352 100644 --- a/src/client_server/alias.rs +++ b/src/client_server/alias.rs @@ -1,9 +1,9 @@ use super::State; -use crate::{ConduitResult, Database, Error, Ruma}; -use ruma::api::client::{ +use crate::{ConduitResult, Database, Error, Ruma, server_server}; +use ruma::api::{federation, client::{ error::ErrorKind, r0::alias::{create_alias, delete_alias, get_alias}, -}; +}}; #[cfg(feature = "conduit_bin")] use rocket::{delete, get, put}; @@ -43,12 +43,25 @@ pub fn delete_alias_route( feature = "conduit_bin", get("/_matrix/client/r0/directory/room/<_>", data = "") )] -pub fn get_alias_route( +pub async fn get_alias_route( db: State<'_, Database>, body: Ruma, ) -> ConduitResult { if body.room_alias.server_name() != db.globals.server_name() { - todo!("ask remote server"); + let response = server_server::send_request( + &db, + body.room_alias.server_name().to_string(), + federation::query::get_room_information::v1::Request { + room_alias: body.room_alias.to_string(), + }, + ) + .await?; + + return Ok(get_alias::Response { + room_id: response.room_id, + servers: response.servers, + } + .into()); } let room_id = db diff --git a/src/client_server/directory.rs b/src/client_server/directory.rs index 279df181..26188f73 100644 --- a/src/client_server/directory.rs +++ b/src/client_server/directory.rs @@ -1,15 +1,18 @@ use super::State; -use crate::{ConduitResult, Database, Error, Result, Ruma}; +use crate::{server_server, ConduitResult, Database, Error, Result, Ruma}; use ruma::{ - api::client::{ - error::ErrorKind, - r0::{ - directory::{ - self, get_public_rooms, get_public_rooms_filtered, get_room_visibility, - set_room_visibility, + api::{ + client::{ + error::ErrorKind, + r0::{ + directory::{ + self, get_public_rooms, get_public_rooms_filtered, get_room_visibility, + set_room_visibility, + }, + room, }, - room, }, + federation, }, events::{ room::{avatar, canonical_alias, guest_access, history_visibility, name, topic}, @@ -29,6 +32,46 @@ pub async fn get_public_rooms_filtered_route( db: State<'_, Database>, body: Ruma, ) -> ConduitResult { + if let Some(other_server) = body + .server + .clone() + .filter(|server| server != &db.globals.server_name().as_str()) + { + let response = server_server::send_request( + &db, + other_server, + federation::directory::get_public_rooms::v1::Request { + limit: body.limit, + since: body.since.clone(), + room_network: federation::directory::get_public_rooms::v1::RoomNetwork::Matrix, + }, + ) + .await?; + + return Ok(get_public_rooms_filtered::Response { + chunk: response + .chunk + .into_iter() + .map(|c| { + // Convert ruma::api::federation::directory::get_public_rooms::v1::PublicRoomsChunk + // to ruma::api::client::r0::directory::PublicRoomsChunk + Ok::<_, Error>( + serde_json::from_str( + &serde_json::to_string(&c) + .expect("PublicRoomsChunk::to_string always works"), + ) + .expect("federation and client-server PublicRoomsChunk are the same type"), + ) + }) + .filter_map(|r| r.ok()) + .collect(), + prev_batch: response.prev_batch, + next_batch: response.next_batch, + total_room_count_estimate: response.total_room_count_estimate, + } + .into()); + } + let limit = body.limit.map_or(10, u64::from); let mut since = 0_u64; @@ -169,26 +212,6 @@ pub async fn get_public_rooms_filtered_route( all_rooms.sort_by(|l, r| r.num_joined_members.cmp(&l.num_joined_members)); - /* - all_rooms.extend_from_slice( - &server_server::send_request( - &db, - "privacytools.io".to_owned(), - ruma::api::federation::v1::get_public_rooms::Request { - limit: Some(20_u32.into()), - since: None, - room_network: ruma::api::federation::v1::get_public_rooms::RoomNetwork::Matrix, - }, - ) - .await - ? - .chunk - .into_iter() - .map(|c| serde_json::from_str(&serde_json::to_string(&c)?)?) - .collect::>(), - ); - */ - let total_room_count_estimate = (all_rooms.len() as u32).into(); let chunk = all_rooms diff --git a/src/client_server/membership.rs b/src/client_server/membership.rs index 0ada7c40..84c0ebd3 100644 --- a/src/client_server/membership.rs +++ b/src/client_server/membership.rs @@ -1,16 +1,24 @@ use super::State; -use crate::{pdu::PduBuilder, ConduitResult, Database, Error, Ruma}; +use crate::{ + client_server, pdu::PduBuilder, server_server, utils, ConduitResult, Database, Error, Ruma, +}; use ruma::{ - api::client::{ - error::ErrorKind, - r0::membership::{ - ban_user, forget_room, get_member_events, invite_user, join_room_by_id, - join_room_by_id_or_alias, joined_members, joined_rooms, kick_user, leave_room, - unban_user, + api::{ + client::{ + error::ErrorKind, + r0::{ + alias, + membership::{ + ban_user, forget_room, get_member_events, invite_user, join_room_by_id, + join_room_by_id_or_alias, joined_members, joined_rooms, kick_user, leave_room, + unban_user, + }, + }, }, + federation, }, events::{room::member, EventType}, - Raw, RoomId, + EventId, Raw, RoomId, RoomVersionId, }; use std::{collections::BTreeMap, convert::TryFrom}; @@ -21,13 +29,81 @@ use rocket::{get, post}; feature = "conduit_bin", post("/_matrix/client/r0/rooms/<_>/join", data = "") )] -pub fn join_room_by_id_route( +pub async fn join_room_by_id_route( db: State<'_, Database>, body: Ruma, ) -> ConduitResult { let sender_id = body.sender_id.as_ref().expect("user is authenticated"); - // TODO: Ask a remote server if we don't have this room + // Ask a remote server if we don't have this room + if !db.rooms.exists(&body.room_id)? && body.room_id.server_name() != db.globals.server_name() { + let make_join_response = server_server::send_request( + &db, + body.room_id.server_name().to_string(), + federation::membership::create_join_event_template::v1::Request { + room_id: body.room_id.clone(), + user_id: sender_id.clone(), + ver: vec![RoomVersionId::Version5, RoomVersionId::Version6], + }, + ) + .await?; + + let mut join_event_stub_value = + serde_json::from_str::(make_join_response.event.json().get()) + .map_err(|_| { + Error::BadServerResponse("Invalid make_join event json received from server.") + })?; + + let join_event_stub = + join_event_stub_value + .as_object_mut() + .ok_or(Error::BadServerResponse( + "Invalid make join event object received from server.", + ))?; + + join_event_stub.insert( + "origin".to_owned(), + db.globals.server_name().to_owned().to_string().into(), + ); + join_event_stub.insert( + "origin_server_ts".to_owned(), + utils::millis_since_unix_epoch().into(), + ); + + // Generate event id + let event_id = EventId::try_from(&*format!( + "${}", + ruma::signatures::reference_hash(&join_event_stub_value) + .expect("ruma can calculate reference hashes") + )) + .expect("ruma's reference hashes are valid event ids"); + + // We don't leave the event id into the pdu because that's only allowed in v1 or v2 rooms + let join_event_stub = join_event_stub_value.as_object_mut().unwrap(); + join_event_stub.remove("event_id"); + + ruma::signatures::hash_and_sign_event( + db.globals.server_name().as_str(), + db.globals.keypair(), + &mut join_event_stub_value, + ) + .expect("event is valid, we just created it"); + + let send_join_response = server_server::send_request( + &db, + body.room_id.server_name().to_string(), + federation::membership::create_join_event::v2::Request { + room_id: body.room_id.clone(), + event_id, + pdu_stub: serde_json::from_value::>(join_event_stub_value) + .expect("Raw::from_value always works"), + }, + ) + .await?; + + dbg!(send_join_response); + todo!("Take send_join_response and 'create' the room using that data"); + } let event = member::MemberEventContent { membership: member::MembershipState::Join, @@ -61,16 +137,28 @@ pub fn join_room_by_id_route( feature = "conduit_bin", post("/_matrix/client/r0/join/<_>", data = "") )] -pub fn join_room_by_id_or_alias_route( +pub async fn join_room_by_id_or_alias_route( db: State<'_, Database>, + db2: State<'_, Database>, body: Ruma, ) -> ConduitResult { - let room_id = RoomId::try_from(body.room_id_or_alias.clone()).or_else(|alias| { - Ok::<_, Error>(db.rooms.id_from_alias(&alias)?.ok_or(Error::BadRequest( - ErrorKind::NotFound, - "Room not found (TODO: Federation).", - ))?) - })?; + let room_id = match RoomId::try_from(body.room_id_or_alias.clone()) { + Ok(room_id) => room_id, + Err(room_alias) => { + client_server::get_alias_route( + db, + Ruma { + body: alias::get_alias::IncomingRequest { room_alias }, + sender_id: body.sender_id.clone(), + device_id: body.device_id.clone(), + json_body: None, + }, + ) + .await? + .0 + .room_id + } + }; let body = Ruma { sender_id: body.sender_id.clone(), @@ -83,7 +171,7 @@ pub fn join_room_by_id_or_alias_route( }; Ok(join_room_by_id_or_alias::Response { - room_id: join_room_by_id_route(db, body)?.0.room_id, + room_id: join_room_by_id_route(db2, body).await?.0.room_id, } .into()) } diff --git a/src/client_server/room.rs b/src/client_server/room.rs index 54e57fd8..b5f1529e 100644 --- a/src/client_server/room.rs +++ b/src/client_server/room.rs @@ -92,13 +92,6 @@ pub fn create_room_route( &db.account_data, )?; - // Figure out preset. We need it for power levels and preset specific events - let visibility = body.visibility.unwrap_or(room::Visibility::Private); - let preset = body.preset.unwrap_or_else(|| match visibility { - room::Visibility::Private => create_room::RoomPreset::PrivateChat, - room::Visibility::Public => create_room::RoomPreset::PublicChat, - }); - // 3. Power levels let mut users = BTreeMap::new(); users.insert(sender_id.clone(), 100.into()); @@ -142,6 +135,14 @@ pub fn create_room_route( )?; // 4. Events set by preset + + // Figure out preset. We need it for preset specific events + let visibility = body.visibility.unwrap_or(room::Visibility::Private); + let preset = body.preset.unwrap_or_else(|| match visibility { + room::Visibility::Private => create_room::RoomPreset::PrivateChat, + room::Visibility::Public => create_room::RoomPreset::PublicChat, + }); + // 4.1 Join Rules db.rooms.append_pdu( PduBuilder { diff --git a/src/error.rs b/src/error.rs index af5405c2..623aa0ef 100644 --- a/src/error.rs +++ b/src/error.rs @@ -27,6 +27,13 @@ pub enum Error { #[from] source: image::error::ImageError, }, + #[error("Could not connect to server.")] + ReqwestError { + #[from] + source: reqwest::Error, + }, + #[error("{0}")] + BadServerResponse(&'static str), #[error("{0}")] BadConfig(&'static str), #[error("{0}")] diff --git a/src/lib.rs b/src/lib.rs index 96236bfc..f761413b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod client_server; +pub mod server_server; mod database; mod error; mod pdu; diff --git a/src/main.rs b/src/main.rs index c7cd837a..93ca74e2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,13 +1,13 @@ #![warn(rust_2018_idioms)] -pub mod push_rules; +pub mod server_server; +pub mod client_server; -mod client_server; +mod push_rules; mod database; mod error; mod pdu; mod ruma_wrapper; -//mod server_server; mod utils; pub use database::Database; @@ -110,10 +110,10 @@ fn setup_rocket() -> rocket::Rocket { client_server::get_key_changes_route, client_server::get_pushers_route, client_server::set_pushers_route, - //server_server::well_known_server, - //server_server::get_server_version, - //server_server::get_server_keys, - //server_server::get_server_keys_deprecated, + server_server::well_known_server, + server_server::get_server_version, + server_server::get_server_keys, + server_server::get_server_keys_deprecated, ], ) .attach(AdHoc::on_attach("Config", |mut rocket| async { diff --git a/src/server_server.rs b/src/server_server.rs index a2141433..0af5546a 100644 --- a/src/server_server.rs +++ b/src/server_server.rs @@ -1,16 +1,15 @@ -use crate::{Database, MatrixResult}; +use crate::{ConduitResult, Database, Result}; use http::header::{HeaderValue, AUTHORIZATION}; -use log::error; use rocket::{get, response::content::Json, State}; -use ruma::api::Endpoint; -use ruma::api::client::error::Error; use ruma::api::federation::discovery::{ - get_server_keys::v2 as get_server_keys, get_server_version::v1 as get_server_version, + get_server_keys, get_server_version::v1 as get_server_version, ServerKey, VerifyKey, }; +use ruma::api::OutgoingRequest; use serde_json::json; use std::{ collections::BTreeMap, convert::TryFrom, + fmt::Debug, time::{Duration, SystemTime}, }; @@ -33,36 +32,51 @@ pub async fn request_well_known(db: &crate::Database, destination: &str) -> Opti Some(body.get("m.server")?.as_str()?.to_owned()) } -pub async fn send_request( +pub async fn send_request( db: &crate::Database, destination: String, request: T, -) -> Option { - let mut http_request: http::Request<_> = request.try_into().unwrap(); - +) -> Result +where + T: Debug, +{ let actual_destination = "https://".to_owned() + &request_well_known(db, &destination) .await .unwrap_or(destination.clone() + ":8448"); - *http_request.uri_mut() = (actual_destination + T::METADATA.path).parse().unwrap(); + + let mut http_request = request + .try_into_http_request(&actual_destination, Some("")) + .unwrap(); let mut request_map = serde_json::Map::new(); if !http_request.body().is_empty() { request_map.insert( "content".to_owned(), - serde_json::to_value(http_request.body()).unwrap(), + serde_json::from_slice(http_request.body()).unwrap(), ); }; request_map.insert("method".to_owned(), T::METADATA.method.to_string().into()); - request_map.insert("uri".to_owned(), T::METADATA.path.into()); - request_map.insert("origin".to_owned(), db.globals.server_name().into()); + request_map.insert( + "uri".to_owned(), + http_request + .uri() + .path_and_query() + .expect("all requests have a path") + .to_string() + .into(), + ); + request_map.insert( + "origin".to_owned(), + db.globals.server_name().as_str().into(), + ); request_map.insert("destination".to_owned(), destination.into()); let mut request_json = request_map.into(); ruma::signatures::sign_json( - db.globals.server_name(), + db.globals.server_name().as_str(), db.globals.keypair(), &mut request_json, ) @@ -72,31 +86,32 @@ pub async fn send_request( .as_object() .unwrap() .values() - .next() - .unwrap() - .as_object() - .unwrap() - .iter() - .map(|(k, v)| (k, v.as_str().unwrap())); + .map(|v| { + v.as_object() + .unwrap() + .iter() + .map(|(k, v)| (k, v.as_str().unwrap())) + }); - for s in signatures { - http_request.headers_mut().insert( - AUTHORIZATION, - HeaderValue::from_str(&format!( - "X-Matrix origin={},key=\"{}\",sig=\"{}\"", - db.globals.server_name(), - s.0, - s.1 - )) - .unwrap(), - ); + for signature_server in signatures { + for s in signature_server { + http_request.headers_mut().insert( + AUTHORIZATION, + HeaderValue::from_str(&format!( + "X-Matrix origin={},key=\"{}\",sig=\"{}\"", + db.globals.server_name(), + s.0, + s.1 + )) + .unwrap(), + ); + } } - let reqwest_response = db - .globals - .reqwest_client() - .execute(http_request.into()) - .await; + let reqwest_request = reqwest::Request::try_from(http_request) + .expect("all http requests are valid reqwest requests"); + + let reqwest_response = db.globals.reqwest_client().execute(reqwest_request).await; // Because reqwest::Response -> http::Response is complicated: match reqwest_response { @@ -117,59 +132,56 @@ pub async fn send_request( .unwrap() .into_iter() .collect(); - Some( - ::try_from(http_response.body(body).unwrap()) - .ok() - .unwrap(), + Ok( + T::IncomingResponse::try_from(http_response.body(body).unwrap()) + .expect("TODO: error handle other server errors"), ) } - Err(e) => { - error!("{}", e); - None - } + Err(e) => Err(e.into()), } } -#[cfg_attr(feature = "conduit_bin",get("/.well-known/matrix/server"))] +#[cfg_attr(feature = "conduit_bin", get("/.well-known/matrix/server"))] pub fn well_known_server() -> Json { - rocket::response::content::Json( - json!({ "m.server": "matrixtesting.koesters.xyz:14004"}).to_string(), - ) + rocket::response::content::Json(json!({ "m.server": "pc.koesters.xyz:59003"}).to_string()) } -#[cfg_attr(feature = "conduit_bin",get("/_matrix/federation/v1/version"))] -pub fn get_server_version() -> MatrixResult { - MatrixResult(Ok(get_server_version::Response { +#[cfg_attr(feature = "conduit_bin", get("/_matrix/federation/v1/version"))] +pub fn get_server_version() -> ConduitResult { + Ok(get_server_version::Response { server: Some(get_server_version::Server { name: Some("Conduit".to_owned()), version: Some(env!("CARGO_PKG_VERSION").to_owned()), }), - })) + } + .into()) } -#[cfg_attr(feature = "conduit_bin",get("/_matrix/key/v2/server"))] +#[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server"))] pub fn get_server_keys(db: State<'_, Database>) -> Json { let mut verify_keys = BTreeMap::new(); verify_keys.insert( format!("ed25519:{}", db.globals.keypair().version()), - get_server_keys::VerifyKey { + VerifyKey { key: base64::encode_config(db.globals.keypair().public_key(), base64::STANDARD_NO_PAD), }, ); let mut response = serde_json::from_slice( - http::Response::try_from(get_server_keys::Response { - server_name: db.globals.server_name().to_owned(), - verify_keys, - old_verify_keys: BTreeMap::new(), - signatures: BTreeMap::new(), - valid_until_ts: SystemTime::now() + Duration::from_secs(60 * 2), + http::Response::try_from(get_server_keys::v2::Response { + server_key: ServerKey { + server_name: db.globals.server_name().to_owned(), + verify_keys, + old_verify_keys: BTreeMap::new(), + signatures: BTreeMap::new(), + valid_until_ts: SystemTime::now() + Duration::from_secs(60 * 2), + }, }) .unwrap() .body(), ) .unwrap(); ruma::signatures::sign_json( - db.globals.server_name(), + db.globals.server_name().as_str(), db.globals.keypair(), &mut response, ) @@ -177,7 +189,7 @@ pub fn get_server_keys(db: State<'_, Database>) -> Json { Json(response.to_string()) } -#[cfg_attr(feature = "conduit_bin",get("/_matrix/key/v2/server/<_key_id>"))] -pub fn get_server_keys_deprecated(db: State<'_, Database>, _key_id: String) -> Json { +#[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server/<_>"))] +pub fn get_server_keys_deprecated(db: State<'_, Database>) -> Json { get_server_keys(db) }