Merge branch 'main' into ganfra/kotlin_bindings

This commit is contained in:
ganfra
2022-11-02 19:06:07 +01:00
35 changed files with 554 additions and 218 deletions

View File

@@ -16,8 +16,73 @@ env:
CARGO_TERM_COLOR: always
MATRIX_SDK_CRYPTO_NODEJS_PATH: bindings/matrix-sdk-crypto-nodejs
MATRIX_SDK_CRYPTO_JS_PATH: bindings/matrix-sdk-crypto-js
# keep in sync with uniffi dependency in root Cargo.toml
UNIFFI_REV: 6ee61a46f59736f93b912f3cf45481f005c63115
jobs:
xtask-linux:
runs-on: ubuntu-latest
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Check xtask cache
uses: actions/cache@v3
id: xtask-cache
with:
path: target/debug/xtask
key: xtask-linux-${{ hashFiles('Cargo.toml', 'xtask/**') }}
- name: Install rust stable toolchain
if: steps.xtask-cache.outputs.cache-hit != 'true'
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Build
if: steps.xtask-cache.outputs.cache-hit != 'true'
uses: actions-rs/cargo@v1
with:
command: build
args: -p xtask
test-uniffi-codegen:
name: Test UniFFI bindings generation
needs: xtask-linux
if: github.event_name == 'push' || !github.event.pull_request.draft
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
profile: minimal
override: true
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Get xtask
uses: actions/cache@v3
with:
path: target/debug/xtask
key: xtask-linux-${{ hashFiles('Cargo.toml', 'xtask/**') }}
- name: Install Uniffi
uses: actions-rs/cargo@v1
with:
command: install
args: uniffi_bindgen --git https://github.com/mozilla/uniffi-rs --rev ${{ env.UNIFFI_REV }}
- name: Build library & generate bindings
run: target/debug/xtask ci bindings
test-matrix-sdk-crypto-nodejs:
name: ${{ matrix.os-name }} [m]-crypto-nodejs, v${{ matrix.node-version }}
if: github.event_name == 'push' || !github.event.pull_request.draft
@@ -27,7 +92,7 @@ jobs:
fail-fast: true
matrix:
os: [ubuntu-latest]
node-version: [14.0, 16.0, 18.0]
node-version: [14.0, 16.0, 18.0, 19.0]
include:
- os: ubuntu-latest
os-name: 🐧
@@ -133,8 +198,37 @@ jobs:
working-directory: ${{ env.MATRIX_SDK_CRYPTO_JS_PATH }}
run: npm run doc
xtask-macos:
runs-on: macos-12
steps:
- name: Checkout repo
uses: actions/checkout@v2
- name: Check xtask cache
uses: actions/cache@v3
id: xtask-cache
with:
path: target/debug/xtask
key: xtask-macos-${{ hashFiles('Cargo.toml', 'xtask/**') }}
- name: Install rust stable toolchain
if: steps.xtask-cache.outputs.cache-hit != 'true'
uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
- name: Build
if: steps.xtask-cache.outputs.cache-hit != 'true'
uses: actions-rs/cargo@v1
with:
command: build
args: -p xtask
test-apple:
name: matrix-rust-components-swift
needs: xtask-macos
runs-on: macos-12
if: github.event_name == 'push' || !github.event.pull_request.draft
@@ -152,15 +246,20 @@ jobs:
- name: Load cache
uses: Swatinem/rust-cache@v1
- name: Get xtask
uses: actions/cache@v3
with:
path: target/debug/xtask
key: xtask-macos-${{ hashFiles('Cargo.toml', 'xtask/**') }}
- name: Install Uniffi
uses: actions-rs/cargo@v1
with:
command: install
# keep in sync with uniffi dependency in root Cargo.toml
args: uniffi_bindgen --git https://github.com/mozilla/uniffi-rs --rev fdb769b567865d9c5c7c682a18d0c1301a039c85
args: uniffi_bindgen --git https://github.com/mozilla/uniffi-rs --rev ${{ env.UNIFFI_REV }}
- name: Build library & bindings
run: cargo xtask swift build-library
run: target/debug/xtask swift build-library
- name: Run XCTests
working-directory: bindings/apple

101
Cargo.lock generated
View File

@@ -528,15 +528,16 @@ dependencies = [
[[package]]
name = "cargo_metadata"
version = "0.14.2"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
checksum = "406c859255d568f4f742b3146d51851f3bfd49f734a2c289d9107c4395ee0062"
dependencies = [
"camino",
"cargo-platform",
"semver",
"serde",
"serde_json",
"thiserror",
]
[[package]]
@@ -677,13 +678,13 @@ dependencies = [
[[package]]
name = "clap"
version = "4.0.16"
version = "4.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2ef582e2c00a63a0c0aa1fb4a4870781c4f5729f51196d3537fa7c1c1992eaa3"
checksum = "335867764ed2de42325fafe6d18b8af74ba97ee0c590fa016f157535b42ab04b"
dependencies = [
"atty",
"bitflags",
"clap_derive 4.0.13",
"clap_derive 4.0.18",
"clap_lex 0.3.0",
"once_cell",
"strsim 0.10.0",
@@ -705,9 +706,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.0.13"
version = "4.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c42f169caba89a7d512b5418b09864543eeb4d497416c917d7137863bd2076ad"
checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3"
dependencies = [
"heck 0.4.0",
"proc-macro-error",
@@ -1441,7 +1442,7 @@ name = "example-emoji-verification"
version = "0.1.0"
dependencies = [
"anyhow",
"clap 4.0.16",
"clap 4.0.18",
"futures",
"matrix-sdk",
"tokio",
@@ -1499,7 +1500,7 @@ name = "example-timeline"
version = "0.1.0"
dependencies = [
"anyhow",
"clap 4.0.16",
"clap 4.0.18",
"futures",
"futures-signals",
"matrix-sdk",
@@ -1825,6 +1826,19 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]]
name = "gloo-utils"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40913a05c8297adca04392f707b1e73b12ba7b8eab7244a4961580b1fd34063c"
dependencies = [
"js-sys",
"serde",
"serde_json",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "goblin"
version = "0.5.4"
@@ -2283,9 +2297,9 @@ dependencies = [
[[package]]
name = "js-sys"
version = "0.3.59"
version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
dependencies = [
"wasm-bindgen",
]
@@ -2440,7 +2454,7 @@ checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb"
[[package]]
name = "matrix-sdk"
version = "0.6.0"
version = "0.6.2"
dependencies = [
"anyhow",
"anymap2",
@@ -2519,7 +2533,7 @@ dependencies = [
[[package]]
name = "matrix-sdk-base"
version = "0.6.0"
version = "0.6.1"
dependencies = [
"assign",
"async-stream",
@@ -2711,6 +2725,7 @@ dependencies = [
"dashmap",
"derive_builder",
"getrandom 0.2.7",
"gloo-utils",
"indexed_db_futures 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
"indexed_db_futures 0.2.3 (git+https://github.com/Hywan/rust-indexed-db?branch=feat-factory-nodejs)",
"js-sys",
@@ -3861,9 +3876,9 @@ dependencies = [
[[package]]
name = "ruma-client-api"
version = "0.15.1"
version = "0.15.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5bcfd3a3853ffdd151fc228441dd9c9e3d835ac85560dface7abda50b3888791"
checksum = "d1e72bc731b4dc8b569aa83915f13e419144b67110d858c65bb74aa05e2dc4b7"
dependencies = [
"assign",
"bytes",
@@ -3878,9 +3893,9 @@ dependencies = [
[[package]]
name = "ruma-common"
version = "0.10.3"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1e629a01f359234798531a99ba83997abd4c15a65b5bcb8354c4171b59c25be"
checksum = "716889595f4edc3cfeb94d9f122e413f73e37d7d80ea1c14196e1004241a3889"
dependencies = [
"base64",
"bytes",
@@ -3931,9 +3946,9 @@ dependencies = [
[[package]]
name = "ruma-macros"
version = "0.10.3"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f7cd8cf8771aaca36042fb7659f4647b05e74a2058d843474dde5e51a56cd85"
checksum = "0f82e91eb61cd86d9287303133ee55b54618eccb75a522cc22a42c15f5bda340"
dependencies = [
"once_cell",
"proc-macro-crate",
@@ -4998,7 +5013,7 @@ checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04"
[[package]]
name = "uniffi"
version = "0.21.0"
source = "git+https://github.com/mozilla/uniffi-rs?rev=fdb769b567865d9c5c7c682a18d0c1301a039c85#fdb769b567865d9c5c7c682a18d0c1301a039c85"
source = "git+https://github.com/mozilla/uniffi-rs?rev=6ee61a46f59736f93b912f3cf45481f005c63115#6ee61a46f59736f93b912f3cf45481f005c63115"
dependencies = [
"anyhow",
"bytes",
@@ -5014,7 +5029,7 @@ dependencies = [
[[package]]
name = "uniffi_bindgen"
version = "0.21.0"
source = "git+https://github.com/mozilla/uniffi-rs?rev=fdb769b567865d9c5c7c682a18d0c1301a039c85#fdb769b567865d9c5c7c682a18d0c1301a039c85"
source = "git+https://github.com/mozilla/uniffi-rs?rev=6ee61a46f59736f93b912f3cf45481f005c63115#6ee61a46f59736f93b912f3cf45481f005c63115"
dependencies = [
"anyhow",
"askama",
@@ -5036,7 +5051,7 @@ dependencies = [
[[package]]
name = "uniffi_build"
version = "0.21.0"
source = "git+https://github.com/mozilla/uniffi-rs?rev=fdb769b567865d9c5c7c682a18d0c1301a039c85#fdb769b567865d9c5c7c682a18d0c1301a039c85"
source = "git+https://github.com/mozilla/uniffi-rs?rev=6ee61a46f59736f93b912f3cf45481f005c63115#6ee61a46f59736f93b912f3cf45481f005c63115"
dependencies = [
"anyhow",
"camino",
@@ -5046,7 +5061,7 @@ dependencies = [
[[package]]
name = "uniffi_macros"
version = "0.21.0"
source = "git+https://github.com/mozilla/uniffi-rs?rev=fdb769b567865d9c5c7c682a18d0c1301a039c85#fdb769b567865d9c5c7c682a18d0c1301a039c85"
source = "git+https://github.com/mozilla/uniffi-rs?rev=6ee61a46f59736f93b912f3cf45481f005c63115#6ee61a46f59736f93b912f3cf45481f005c63115"
dependencies = [
"bincode",
"camino",
@@ -5064,7 +5079,7 @@ dependencies = [
[[package]]
name = "uniffi_meta"
version = "0.21.0"
source = "git+https://github.com/mozilla/uniffi-rs?rev=fdb769b567865d9c5c7c682a18d0c1301a039c85#fdb769b567865d9c5c7c682a18d0c1301a039c85"
source = "git+https://github.com/mozilla/uniffi-rs?rev=6ee61a46f59736f93b912f3cf45481f005c63115#6ee61a46f59736f93b912f3cf45481f005c63115"
dependencies = [
"serde",
]
@@ -5223,21 +5238,19 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.82"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if",
"serde",
"serde_json",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.82"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
"log",
@@ -5250,9 +5263,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-futures"
version = "0.4.32"
version = "0.4.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad"
checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
dependencies = [
"cfg-if",
"js-sys",
@@ -5262,9 +5275,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.82"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -5272,9 +5285,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.82"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
@@ -5285,15 +5298,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.82"
version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "wasm-bindgen-test"
version = "0.3.32"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "513df541345bb9fcc07417775f3d51bbb677daf307d8035c0afafd87dc2e6599"
checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d"
dependencies = [
"console_error_panic_hook",
"js-sys",
@@ -5305,9 +5318,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-test-macro"
version = "0.3.32"
version = "0.3.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6150d36a03e90a3cf6c12650be10626a9902d70c5270fd47d7a47e5389a10d56"
checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7"
dependencies = [
"proc-macro2",
"quote",
@@ -5373,7 +5386,7 @@ dependencies = [
[[package]]
name = "weedle2"
version = "4.0.0"
source = "git+https://github.com/mozilla/uniffi-rs?rev=fdb769b567865d9c5c7c682a18d0c1301a039c85#fdb769b567865d9c5c7c682a18d0c1301a039c85"
source = "git+https://github.com/mozilla/uniffi-rs?rev=6ee61a46f59736f93b912f3cf45481f005c63115#6ee61a46f59736f93b912f3cf45481f005c63115"
dependencies = [
"nom",
]
@@ -5536,7 +5549,7 @@ name = "xtask"
version = "0.1.0"
dependencies = [
"camino",
"clap 3.2.22",
"clap 4.0.18",
"serde",
"serde_json",
"uniffi_bindgen",

View File

@@ -18,10 +18,10 @@ resolver = "2"
[workspace.dependencies]
ruma = { version = "0.7.4", features = ["client-api-c"] }
tracing = { version = "0.1.36", default-features = false, features = ["std"] }
uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "fdb769b567865d9c5c7c682a18d0c1301a039c85" }
uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "fdb769b567865d9c5c7c682a18d0c1301a039c85" }
uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "fdb769b567865d9c5c7c682a18d0c1301a039c85" }
uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "fdb769b567865d9c5c7c682a18d0c1301a039c85", features = ["builtin-bindgen"] }
uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "6ee61a46f59736f93b912f3cf45481f005c63115" }
uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "6ee61a46f59736f93b912f3cf45481f005c63115" }
uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "6ee61a46f59736f93b912f3cf45481f005c63115" }
uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "6ee61a46f59736f93b912f3cf45481f005c63115", features = ["builtin-bindgen"] }
vodozemac = "0.3.0"
zeroize = "1.3.0"

View File

@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "MatrixSDKCrypto"
s.version = "0.1.2"
s.version = "0.1.5"
s.summary = "Uniffi based bindings for the Rust SDK crypto crate."
s.homepage = "https://github.com/matrix-org/matrix-rust-sdk"
s.license = { :type => "Apache License, Version 2.0", :file => "LICENSE" }

View File

@@ -28,6 +28,7 @@ pub use error::{
use js_int::UInt;
pub use logger::{set_logger, Logger};
pub use machine::{KeyRequestPair, OlmMachine};
use matrix_sdk_common::deserialized_responses::VerificationState;
use matrix_sdk_crypto::{
types::{EventEncryptionAlgorithm as RustEventEncryptionAlgorithm, SigningKey},
EncryptionSettings as RustEncryptionSettings, LocalTrust,
@@ -458,6 +459,10 @@ pub struct DecryptedEvent {
/// key to us. Is empty if the key came directly from the sender of the
/// event.
pub forwarding_curve25519_chain: Vec<String>,
/// The verification state of the device that sent us the event, note this
/// is the state of the device at the time of decryption. It may change in
/// the future if a device gets verified or deleted.
pub verification_state: VerificationState,
}
/// Struct representing the state of our private cross signing keys, it shows

View File

@@ -629,6 +629,7 @@ impl OlmMachine {
.get(&DeviceKeyAlgorithm::Ed25519)
.cloned(),
forwarding_curve25519_chain: vec![],
verification_state: encryption_info.verification_state,
}
}
})

View File

@@ -82,6 +82,7 @@ dictionary DecryptedEvent {
string sender_curve25519_key;
string? claimed_ed25519_key;
sequence<string> forwarding_curve25519_chain;
VerificationState verification_state;
};
dictionary Device {
@@ -254,6 +255,12 @@ enum LocalTrust {
"Unset",
};
enum VerificationState {
"Trusted",
"Untrusted",
"UnknownDevice",
};
enum EventEncryptionAlgorithm {
"OlmV1Curve25519AesSha2",
"MegolmV1AesSha2",

View File

@@ -33,8 +33,8 @@ matrix-sdk-indexeddb = { version = "0.2.0", path = "../../crates/matrix-sdk-inde
matrix-sdk-qrcode = { version = "0.4.0", path = "../../crates/matrix-sdk-qrcode", optional = true }
ruma = { workspace = true, features = ["js", "rand", "unstable-msc2676", "unstable-msc2677"] }
vodozemac = { workspace = true, features = ["js"] }
wasm-bindgen = "0.2.80"
wasm-bindgen-futures = "0.4.30"
wasm-bindgen = "0.2.83"
wasm-bindgen-futures = "0.4.33"
js-sys = "0.3.49"
console_error_panic_hook = "0.1.7"
serde_json = "1.0.79"

View File

@@ -37,7 +37,7 @@
"node": ">= 10"
},
"scripts": {
"build": "cross-env RUSTFLAGS='-C opt-level=z' wasm-pack build --release --target nodejs --scope matrix-org --out-dir ./pkg",
"build": "cross-env RUSTFLAGS='-C opt-level=z' WASM_BINDGEN_WEAKREF=1 wasm-pack build --release --target nodejs --scope matrix-org --out-dir ./pkg",
"test": "jest --verbose",
"doc": "typedoc --tsconfig .",
"prepack": "npm run build && npm run test",

View File

@@ -28,7 +28,17 @@ pub struct OlmMachine {
#[wasm_bindgen]
impl OlmMachine {
/// Create a new memory based `OlmMachine`.
/// Constructor will always fail. To create a new `OlmMachine`, please use
/// the `initialize` method.
///
/// Why this pattern? `initialize` returns a `Promise`. Returning a
// `Promise` from a constructor is not idiomatic in JavaScript.
#[wasm_bindgen(constructor)]
pub fn new() -> Result<OlmMachine, JsError> {
Err(JsError::new("To build an `OlmMachine`, please use the `initialize` method"))
}
/// Create a new `OlmMachine`.
///
/// The created machine will keep the encryption keys either in a IndexedDB
/// based store, or in a memory store and once the objects is dropped,
@@ -49,9 +59,7 @@ impl OlmMachine {
///
/// * `store_passphrase` - The passphrase that should be used to encrypt the
/// IndexedDB based
#[wasm_bindgen(constructor)]
#[allow(clippy::new_ret_no_self)]
pub fn new(
pub fn initialize(
user_id: &identifiers::UserId,
device_id: &identifiers::DeviceId,
store_name: Option<String>,

View File

@@ -53,7 +53,7 @@ describe(OlmMachine.name, () => {
const room = new RoomId('!baz:matrix.org');
function machine(new_user, new_device) {
return new OlmMachine(new_user || user, new_device || device);
return OlmMachine.initialize(new_user || user, new_device || device);
}
test('can read user devices', async () => {
@@ -116,7 +116,7 @@ describe('Key Verification', () => {
const deviceId2 = new DeviceId('bob_device');
function machine(new_user, new_device) {
return new OlmMachine(new_user || userId1, new_device || deviceId1);
return OlmMachine.initialize(new_user || userId1, new_device || deviceId1);
}
describe('SAS', () => {

View File

@@ -25,7 +25,7 @@ require('fake-indexeddb/auto');
describe(OlmMachine.name, () => {
test('can be instantiated with the async initializer', async () => {
expect(await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'))).toBeInstanceOf(OlmMachine);
expect(await OlmMachine.initialize(new UserId('@foo:bar.org'), new DeviceId('baz'))).toBeInstanceOf(OlmMachine);
});
test('can be instantiated with a store', async () => {
@@ -36,7 +36,7 @@ describe(OlmMachine.name, () => {
let store_passphrase = 'world';
// Creating a new Olm machine.
expect(await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase)).toBeInstanceOf(OlmMachine);
expect(await OlmMachine.initialize(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase)).toBeInstanceOf(OlmMachine);
// Oh, there is 2 databases now, prefixed by `store_name`.
let databases = await indexedDB.databases();
@@ -48,7 +48,7 @@ describe(OlmMachine.name, () => {
]);
// Creating a new Olm machine, with the stored state.
expect(await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase)).toBeInstanceOf(OlmMachine);
expect(await OlmMachine.initialize(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase)).toBeInstanceOf(OlmMachine);
// Same number of databases.
expect(await indexedDB.databases()).toHaveLength(2);
@@ -62,7 +62,7 @@ describe(OlmMachine.name, () => {
let err = null;
try {
await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase);
await OlmMachine.initialize(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase);
} catch (error) {
err = error;
}
@@ -77,7 +77,7 @@ describe(OlmMachine.name, () => {
let err = null;
try {
await new OlmMachine(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase);
await OlmMachine.initialize(new UserId('@foo:bar.org'), new DeviceId('baz'), store_name, store_passphrase);
} catch (error) {
err = error;
}
@@ -91,7 +91,7 @@ describe(OlmMachine.name, () => {
const room = new RoomId('!baz:matrix.org');
function machine(new_user, new_device) {
return new OlmMachine(new_user || user, new_device || device);
return OlmMachine.initialize(new_user || user, new_device || device);
}
test('can read user ID', async () => {

View File

@@ -68,7 +68,7 @@ describe(Tracing.name, () => {
};
// Do something that emits a `DEBUG` log.
await new OlmMachine(new UserId('@alice:example.org'), new DeviceId('foo'));
await OlmMachine.initialize(new UserId('@alice:example.org'), new DeviceId('foo'));
console.debug = originalConsoleDebug;
testPostState();

View File

@@ -1,3 +1,4 @@
const { Agent } = require('https');
const { DownloaderHelper } = require('node-downloader-helper');
const { version } = require("./package.json");
const { platform, arch } = process
@@ -22,6 +23,11 @@ function download_lib(libname) {
console.info(`Downloading lib ${libname} from ${url}`);
const dl = new DownloaderHelper(url, __dirname, {
override: true,
httpsRequestOptions: {
// Disable keepalive to prevent the process hanging open.
// https://github.com/matrix-org/matrix-rust-sdk/issues/1160
agent: new Agent({ keepAlive: false }),
},
});
dl.on('end', () => console.info('Download Completed'));

View File

@@ -13,7 +13,7 @@ use matrix_sdk::{
session::get_login_types,
sync::sync_events::v3::Filter,
},
events::room::MediaSource,
events::{room::MediaSource, AnyToDeviceEvent},
serde::Raw,
TransactionId, UInt,
},
@@ -49,11 +49,29 @@ pub struct Client {
impl Client {
pub fn new(client: MatrixClient, state: ClientState) -> Self {
let session_verification_controller: Arc<
matrix_sdk::locks::RwLock<Option<SessionVerificationController>>,
> = Default::default();
let ctrl = session_verification_controller.clone();
client.add_event_handler(move |ev: AnyToDeviceEvent| {
let ctrl = ctrl.clone();
async move {
if let Some(session_verification_controller) = &*ctrl.clone().read().await {
session_verification_controller.process_to_device_message(ev).await;
} else {
tracing::warn!(
"received to-device message, but verification controller isn't ready"
);
}
}
});
Client {
client,
state: Arc::new(RwLock::new(state)),
delegate: Arc::new(RwLock::new(None)),
session_verification_controller: Arc::new(matrix_sdk::locks::RwLock::new(None)),
session_verification_controller,
}
}
@@ -234,7 +252,6 @@ impl Client {
{
return Ok(Arc::new(session_verification_controller.clone()));
}
let user_id = self.client.user_id().context("Failed retrieving current user_id")?;
let user_identity = self
.client
@@ -263,8 +280,7 @@ impl Client {
}
/// Process a sync error and return loop control accordingly
fn process_sync_error(&self, sync_error: Error) -> LoopCtrl {
let mut control = LoopCtrl::Continue;
pub(crate) fn process_sync_error(&self, sync_error: Error) -> LoopCtrl {
if let Some(RumaApiError::ClientApi(error)) = sync_error.as_ruma_api_error() {
if let ErrorKind::UnknownToken { soft_logout } = error.kind {
self.state.write().unwrap().is_soft_logout = soft_logout;
@@ -272,10 +288,12 @@ impl Client {
delegate.did_update_restore_token();
delegate.did_receive_auth_error(soft_logout);
}
control = LoopCtrl::Break
return LoopCtrl::Break;
}
}
control
tracing::warn!("Ignoring sync error: {:?}", sync_error);
LoopCtrl::Continue
}
}
@@ -315,7 +333,6 @@ impl Client {
let client = self.client.clone();
let state = self.state.clone();
let delegate = self.delegate.clone();
let session_verification_controller = self.session_verification_controller.clone();
let local_self = self.clone();
RUNTIME.spawn(async move {
let mut filter = FilterDefinition::default();
@@ -337,7 +354,7 @@ impl Client {
client
.sync_with_result_callback(sync_settings, |result| async {
Ok(if let Ok(sync_response) = result {
Ok(if result.is_ok() {
if !state.read().unwrap().has_first_synced {
state.write().unwrap().has_first_synced = true;
}
@@ -353,14 +370,6 @@ impl Client {
delegate.did_receive_sync_update()
}
if let Some(session_verification_controller) =
&*session_verification_controller.read().await
{
session_verification_controller
.process_to_device_messages(sync_response.to_device_events)
.await;
}
LoopCtrl::Continue
} else {
local_self.process_sync_error(result.err().unwrap())

View File

@@ -106,64 +106,66 @@ impl SessionVerificationController {
})
}
pub async fn process_to_device_messages(&self, to_device_events: Vec<Raw<AnyToDeviceEvent>>) {
let sas_verification = self.sas_verification.clone();
for event in to_device_events.into_iter().filter_map(|e| e.deserialize().ok()) {
match event {
AnyToDeviceEvent::KeyVerificationReady(event) => {
if !self.is_transaction_id_valid(event.content.transaction_id.to_string()) {
return;
}
self.start_sas_verification().await;
pub async fn process_to_device_message(&self, event: AnyToDeviceEvent) {
match event {
AnyToDeviceEvent::KeyVerificationReady(event) => {
if !self.is_transaction_id_valid(event.content.transaction_id.to_string()) {
return;
}
AnyToDeviceEvent::KeyVerificationCancel(event) => {
if !self.is_transaction_id_valid(event.content.transaction_id.to_string()) {
return;
}
if let Some(delegate) = &*self.delegate.read().unwrap() {
delegate.did_cancel()
}
self.start_sas_verification().await;
}
AnyToDeviceEvent::KeyVerificationCancel(event) => {
if !self.is_transaction_id_valid(event.content.transaction_id.to_string()) {
return;
}
AnyToDeviceEvent::KeyVerificationKey(event) => {
if !self.is_transaction_id_valid(event.content.transaction_id.to_string()) {
return;
}
if let Some(sas_verification) = &*sas_verification.read().unwrap() {
if let Some(emojis) = sas_verification.emoji() {
if let Some(delegate) = &*self.delegate.read().unwrap() {
let emojis = emojis
.iter()
.map(|e| {
Arc::new(SessionVerificationEmoji {
symbol: e.symbol.to_owned(),
description: e.description.to_owned(),
})
if let Some(delegate) = &*self.delegate.read().unwrap() {
delegate.did_cancel()
}
}
AnyToDeviceEvent::KeyVerificationKey(event) => {
if !self.is_transaction_id_valid(event.content.transaction_id.to_string()) {
return;
}
if let Some(sas_verification) = &*self.sas_verification.read().unwrap() {
if let Some(emojis) = sas_verification.emoji() {
if let Some(delegate) = &*self.delegate.read().unwrap() {
let emojis = emojis
.iter()
.map(|e| {
Arc::new(SessionVerificationEmoji {
symbol: e.symbol.to_owned(),
description: e.description.to_owned(),
})
.collect::<Vec<_>>();
})
.collect::<Vec<_>>();
delegate.did_receive_verification_data(emojis);
}
} else if let Some(delegate) = &*self.delegate.read().unwrap() {
delegate.did_fail()
delegate.did_receive_verification_data(emojis);
}
} else if let Some(delegate) = &*self.delegate.read().unwrap() {
delegate.did_fail()
}
} else if let Some(delegate) = &*self.delegate.read().unwrap() {
delegate.did_fail()
}
AnyToDeviceEvent::KeyVerificationDone(event) => {
if !self.is_transaction_id_valid(event.content.transaction_id.to_string()) {
return;
}
if let Some(delegate) = &*self.delegate.read().unwrap() {
delegate.did_finish()
}
}
_ => (),
}
AnyToDeviceEvent::KeyVerificationDone(event) => {
if !self.is_transaction_id_valid(event.content.transaction_id.to_string()) {
return;
}
if let Some(delegate) = &*self.delegate.read().unwrap() {
delegate.did_finish()
}
}
_ => (),
}
}
pub async fn process_to_device_messages(&self, to_device_events: Vec<Raw<AnyToDeviceEvent>>) {
for event in to_device_events.into_iter().filter_map(|e| e.deserialize().ok()) {
self.process_to_device_message(event).await;
}
}

View File

@@ -17,7 +17,7 @@ use matrix_sdk::ruma::{
assign, IdParseError, OwnedRoomId,
};
pub use matrix_sdk::{
Client as MatrixClient, RoomListEntry as MatrixRoomEntry,
Client as MatrixClient, LoopCtrl, RoomListEntry as MatrixRoomEntry,
SlidingSyncBuilder as MatrixSlidingSyncBuilder, SlidingSyncMode, SlidingSyncState,
};
use tokio::task::JoinHandle;
@@ -516,6 +516,7 @@ impl SlidingSync {
let inner_spawn = spawn.clone();
{
let mut sync_handle = self.sync_handle.write().unwrap();
let client = self.client.clone();
if let Some(handle) = sync_handle.take() {
handle.abort();
@@ -528,9 +529,11 @@ impl SlidingSync {
let update = match stream.next().await {
Some(Ok(u)) => u,
Some(Err(e)) => {
// FIXME: send this over the FFI
tracing::warn!("Sliding Sync failure: {:?}", e);
continue;
if client.process_sync_error(e) == LoopCtrl::Break {
break;
} else {
continue;
}
}
None => {
tracing::debug!("No update from loop, cancelled");

View File

@@ -150,6 +150,10 @@ impl TimelineItem {
Arc::new(VirtualTimelineItem(vt))
})
}
pub fn fmt_debug(&self) -> String {
format!("{:#?}", self.0)
}
}
pub struct EventTimelineItem(pub(crate) matrix_sdk::room::timeline::EventTimelineItem);
@@ -193,6 +197,10 @@ impl EventTimelineItem {
pub fn raw(&self) -> Option<String> {
self.0.raw().map(|r| r.json().get().to_owned())
}
pub fn fmt_debug(&self) -> String {
format!("{:#?}", self.0)
}
}
#[derive(Clone, uniffi::Object)]

View File

@@ -102,7 +102,12 @@ where
self.0.poll_ready(cx)
}
fn call(&mut self, req: http::Request<B>) -> Self::Future {
fn call(&mut self, mut req: http::Request<B>) -> Self::Future {
// When the AppServiceRouter is nested inside another axum Router under
// a path that includes path parameters, those should not be received by
// the Path extractor used inside the `handlers` module.
req.extensions_mut().clear();
AppServiceRouteFuture(self.0.call(req))
}
}

View File

@@ -9,7 +9,7 @@ name = "matrix-sdk-base"
readme = "README.md"
repository = "https://github.com/matrix-org/matrix-rust-sdk"
rust-version = "1.62"
version = "0.6.0"
version = "0.6.1"
[package.metadata.docs.rs]
all-features = true
@@ -58,4 +58,4 @@ tracing-subscriber = { version = "0.3.11", features = ["env-filter"] }
tokio = { version = "1.17.0", default-features = false, features = ["rt-multi-thread", "macros"] }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
wasm-bindgen-test = "0.3.30"
wasm-bindgen-test = "0.3.33"

View File

@@ -27,7 +27,7 @@ serde = "1.0.136"
[target.'cfg(target_arch = "wasm32")'.dependencies]
async-lock = "2.5.0"
futures-util = { version = "0.3.21", default-features = false, features = ["channel"] }
wasm-bindgen-futures = { version = "0.4.30", optional = true }
wasm-bindgen-futures = { version = "0.4.33", optional = true }
wasm-timer = "0.2.5"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
@@ -35,4 +35,4 @@ tokio = { version = "1.17.0", default-features = false, features = ["rt", "sync"
[dev-dependencies]
matrix-sdk-test = { path = "../../testing/matrix-sdk-test/", version= "0.6.0"}
wasm-bindgen-test = "0.3.30"
wasm-bindgen-test = "0.3.33"

View File

@@ -24,18 +24,19 @@ async-trait = "0.1.53"
base64 = "0.13.0"
dashmap = { version = "5.2.0", optional = true }
derive_builder = "0.11.2"
gloo-utils = { version = "0.1", features = ["serde"] }
indexed_db_futures = "0.2.3"
indexed_db_futures_nodejs = { version = "0.2.3", package = "indexed_db_futures", git = "https://github.com/Hywan/rust-indexed-db", branch = "feat-factory-nodejs", optional = true }
js-sys = { version = "0.3.58" }
matrix-sdk-base = { version = "0.6.0", path = "../matrix-sdk-base", features = ["js"] }
matrix-sdk-crypto = { version = "0.6.0", path = "../matrix-sdk-crypto", features = ["js"], optional = true }
matrix-sdk-store-encryption = { version = "0.2.0", path = "../matrix-sdk-store-encryption" }
indexed_db_futures = "0.2.3"
indexed_db_futures_nodejs = { version = "0.2.3", package = "indexed_db_futures", git = "https://github.com/Hywan/rust-indexed-db", branch = "feat-factory-nodejs", optional = true }
ruma = { workspace = true }
serde = "1.0.136"
serde_json = "1.0.79"
thiserror = "1.0.30"
tracing = { workspace = true }
wasm-bindgen = { version = "0.2.80", features = ["serde-serialize"] }
wasm-bindgen = "0.2.83"
web-sys = { version = "0.3.57", features = ["IdbKeyRange"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
@@ -48,4 +49,4 @@ matrix-sdk-common = { path = "../matrix-sdk-common", features = ["js"] }
matrix-sdk-crypto = { path = "../matrix-sdk-crypto", features = ["js", "testing"] }
matrix-sdk-test = { path = "../../testing/matrix-sdk-test" }
uuid = "1.0.0"
wasm-bindgen-test = "0.3.30"
wasm-bindgen-test = "0.3.33"

View File

@@ -19,6 +19,7 @@ use std::{
use async_trait::async_trait;
use dashmap::DashSet;
use gloo_utils::format::JsValueSerdeExt;
use matrix_sdk_base::locks::Mutex;
use matrix_sdk_crypto::{
olm::{

View File

@@ -23,6 +23,7 @@ use std::{
use anyhow::anyhow;
use async_trait::async_trait;
use derive_builder::Builder;
use gloo_utils::format::JsValueSerdeExt;
use js_sys::Date as JsDate;
use matrix_sdk_base::{
deserialized_responses::MemberEvent,

View File

@@ -9,7 +9,7 @@ name = "matrix-sdk"
readme = "README.md"
repository = "https://github.com/matrix-org/matrix-rust-sdk"
rust-version = "1.62"
version = "0.6.0"
version = "0.6.2"
[package.metadata.docs.rs]
features = ["docsrs"]
@@ -43,11 +43,10 @@ image-proc = ["dep:image"]
image-rayon = ["image-proc", "image?/jpeg_rayon"]
experimental-room-preview = []
experimental-timeline = []
experimental-timeline = ["ruma/unstable-msc2676", "ruma/unstable-msc2677"]
sliding-sync = [
"matrix-sdk-base/sliding-sync",
"anyhow",
"dep:derive_builder",
]
@@ -134,7 +133,7 @@ tracing-subscriber = { version = "0.3.11", features = ["env-filter"] }
[target.'cfg(target_arch = "wasm32")'.dev-dependencies]
getrandom = { version = "0.2.6", default-features = false, features = ["js"] }
wasm-bindgen-test = "0.3.30"
wasm-bindgen-test = "0.3.33"
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
ctor = "0.1.23"

View File

@@ -193,6 +193,11 @@ pub enum Error {
#[error(transparent)]
ImageError(#[from] ImageError),
/// An error occurred within sliding-sync
#[cfg(feature = "sliding-sync")]
#[error(transparent)]
SlidingSync(#[from] crate::sliding_sync::Error),
/// An other error was raised
/// this might happen because encryption was enabled on the base-crate
/// but not here and that raised.

View File

@@ -58,8 +58,6 @@ impl TimelineInner {
) {
let meta = TimelineEventMetadata {
sender: own_user_id.to_owned(),
origin_server_ts: None,
raw_event: None,
is_own_event: true,
relations: None,
// FIXME: Should we supply something here for encrypted rooms?
@@ -100,15 +98,15 @@ impl TimelineInner {
let is_own_event = sender == own_user_id;
let meta = TimelineEventMetadata {
raw_event: Some(raw),
sender,
origin_server_ts: Some(event.origin_server_ts()),
is_own_event,
relations: event.relations().cloned(),
encryption_info,
};
let flow = Flow::Remote {
event_id: event.event_id().to_owned(),
origin_server_ts: event.origin_server_ts(),
raw_event: raw,
txn_id: event.transaction_id().map(ToOwned::to_owned),
position,
};
@@ -124,6 +122,8 @@ enum Flow {
Remote {
event_id: OwnedEventId,
txn_id: Option<OwnedTransactionId>,
origin_server_ts: MilliSecondsSinceUnixEpoch,
raw_event: Raw<AnySyncTimelineEvent>,
position: TimelineItemPosition,
},
}
@@ -135,12 +135,24 @@ impl Flow {
Self::Local { txn_id } => TimelineKey::TransactionId(txn_id.to_owned()),
}
}
fn origin_server_ts(&self) -> Option<MilliSecondsSinceUnixEpoch> {
match self {
Flow::Local { .. } => None,
Flow::Remote { origin_server_ts, .. } => Some(*origin_server_ts),
}
}
fn raw_event(&self) -> Option<&Raw<AnySyncTimelineEvent>> {
match self {
Flow::Local { .. } => None,
Flow::Remote { raw_event, .. } => Some(raw_event),
}
}
}
struct TimelineEventMetadata {
raw_event: Option<Raw<AnySyncTimelineEvent>>,
sender: OwnedUserId,
origin_server_ts: Option<MilliSecondsSinceUnixEpoch>,
is_own_event: bool,
relations: Option<Relations>,
encryption_info: Option<EncryptionInfo>,
@@ -382,36 +394,52 @@ impl<'a> TimelineEventHandler<'a> {
sender: self.meta.sender.to_owned(),
content,
reactions,
origin_server_ts: self.meta.origin_server_ts,
origin_server_ts: self.flow.origin_server_ts(),
is_own: self.meta.is_own_event,
encryption_info: self.meta.encryption_info.clone(),
raw: self.meta.raw_event.clone(),
raw: self.flow.raw_event().cloned(),
};
let item = Arc::new(TimelineItem::Event(item));
let mut lock = self.timeline.items.lock_mut();
match &self.flow {
Flow::Local { .. }
| Flow::Remote { position: TimelineItemPosition::End, txn_id: None, .. } => {
Flow::Local { .. } => {
lock.push_cloned(item);
}
Flow::Remote { position: TimelineItemPosition::Start, txn_id: None, .. } => {
lock.insert_cloned(0, item);
}
Flow::Remote { txn_id: Some(txn_id), event_id, position } => {
if let Some((idx, _old_item)) = find_event(&lock, txn_id) {
// TODO: Check whether anything is different about the old and new item?
lock.set_cloned(idx, item);
} else {
debug!(
%txn_id, %event_id,
"Received event with transaction ID, but didn't find matching timeline item"
Flow::Remote { txn_id, event_id, position, raw_event, .. } => {
if let Some(txn_id) = txn_id {
if let Some((idx, _old_item)) = find_event(&lock, txn_id) {
// TODO: Check whether anything is different about the
// old and new item?
lock.set_cloned(idx, item);
return;
} else {
warn!(
%txn_id, %event_id,
"Received event with transaction ID, but didn't \
find matching timeline item"
);
}
}
if let Some((idx, old_item)) = find_event(&lock, event_id) {
warn!(
?item,
?old_item,
raw = raw_event.json().get(),
"Received event with an ID we already have a timeline item for"
);
match position {
TimelineItemPosition::Start => lock.insert_cloned(0, item),
TimelineItemPosition::End => lock.push_cloned(item),
}
// With /messages and /sync sometimes disagreeing on order
// of messages, we might want to change the position in some
// circumstances, but for now this should be good enough.
lock.set_cloned(idx, item);
return;
}
match position {
TimelineItemPosition::Start => lock.insert_cloned(0, item),
TimelineItemPosition::End => lock.push_cloned(item),
}
}
}

View File

@@ -12,6 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use std::fmt;
use indexmap::IndexMap;
use matrix_sdk_base::deserialized_responses::EncryptionInfo;
#[cfg(feature = "experimental-room-preview")]
@@ -32,7 +34,7 @@ use ruma::{
/// There is always one main event that gives the `EventTimelineItem` its
/// identity (see [key](Self::key)) but in many cases, additional events like
/// reactions and edits are also part of the item.
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct EventTimelineItem {
pub(super) key: TimelineKey,
// If this item is a local echo that has been acknowledged by the server
@@ -49,6 +51,22 @@ pub struct EventTimelineItem {
pub(super) raw: Option<Raw<AnySyncTimelineEvent>>,
}
impl fmt::Debug for EventTimelineItem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("EventTimelineItem")
.field("key", &self.key)
.field("event_id", &self.event_id)
.field("sender", &self.sender)
.field("content", &self.content)
.field("reactions", &self.reactions)
.field("origin_server_ts", &self.origin_server_ts)
.field("is_own", &self.is_own)
.field("encryption_info", &self.encryption_info)
// skip raw, too noisy
.finish_non_exhaustive()
}
}
macro_rules! build {
(
$ty:ident {
@@ -234,6 +252,12 @@ impl PartialEq<TimelineKey> for &EventId {
}
}
impl PartialEq<TimelineKey> for &OwnedEventId {
fn eq(&self, key: &TimelineKey) -> bool {
matches!(key, TimelineKey::EventId(event_id) if event_id == *self)
}
}
/// Some details of an [`EventTimelineItem`] that may require server requests
/// other than just the regular
/// [`sync_events`][ruma::api::client::sync::sync_events].

View File

@@ -29,7 +29,7 @@ use ruma::{
events::{reaction::Relation as AnnotationRelation, AnyMessageLikeEventContent},
OwnedEventId, OwnedUserId, TransactionId, UInt,
};
use tracing::{debug, error, instrument};
use tracing::{error, instrument, warn};
use super::{Joined, Room};
use crate::{
@@ -236,6 +236,6 @@ fn add_event_id(items: &TimelineInner, txn_id: &TransactionId, event_id: OwnedEv
}
}
} else {
debug!(%txn_id, "Timeline item not found, can't mark as sent");
warn!(%txn_id, "Timeline item not found, can't add event ID");
}
}

View File

@@ -15,7 +15,6 @@
use std::{fmt::Debug, sync::Arc};
use anyhow::{bail, Context};
use futures_core::stream::Stream;
use futures_signals::signal::Mutable;
use matrix_sdk_base::deserialized_responses::{SyncResponse, SyncTimelineEvent};
@@ -27,10 +26,21 @@ use ruma::{
events::RoomEventType,
OwnedRoomId, RoomId, UInt,
};
use thiserror::Error;
use url::Url;
use crate::{Client, Result};
/// Internal representation of errors in Sliding Sync
#[derive(Error, Debug)]
#[non_exhaustive]
pub enum Error {
#[error("Received response for {found} lists, yet we have {expected}.")]
BadViewsCount { found: usize, expected: usize },
#[error("The sliding sync response could not be handled: {0}")]
BadResponse(String),
}
/// The state the [`SlidingSyncView`] is in.
///
/// The lifetime of a SlidingSync usually starts at a `Preload`, getting a fast
@@ -442,13 +452,15 @@ impl SlidingSync {
&self,
resp: v4::Response,
views: &[SlidingSyncView],
) -> anyhow::Result<UpdateSummary> {
) -> Result<UpdateSummary, crate::Error> {
let mut processed = self.client.process_sliding_sync(resp.clone()).await?;
tracing::info!("main client processed.");
self.pos.replace(Some(resp.pos));
let mut updated_views = Vec::new();
if resp.lists.len() != views.len() {
bail!("Received response for {} lists, yet we have {}", resp.lists.len(), views.len());
return Err(
Error::BadViewsCount { found: resp.lists.len(), expected: views.len() }.into()
);
}
for (view, updates) in std::iter::zip(views, &resp.lists) {
@@ -497,23 +509,18 @@ impl SlidingSync {
/// Run this stream to receive new updates from the server.
pub async fn stream<'a>(
&self,
) -> anyhow::Result<impl Stream<Item = anyhow::Result<UpdateSummary>> + '_> {
) -> Result<impl Stream<Item = Result<UpdateSummary, crate::Error>> + '_, crate::Error> {
let views = self.views.lock_ref().to_vec();
let extensions = self.extensions.clone();
let client = self.client.clone();
Ok(async_stream::try_stream! {
Ok(async_stream::stream! {
let mut remaining_views = views.clone();
let mut remaining_generators: Vec<SlidingSyncViewRequestGenerator<'_>> = views
.iter()
.map(SlidingSyncView::request_generator)
.collect();
loop {
#[cfg(feature = "e2e-encryption")]
if let Err(e) = client.send_outgoing_requests().await {
tracing::error!(error = ?e, "Error while sending outgoing E2EE requests");
}
let mut requests = Vec::new();
let mut new_remaining_generators = Vec::new();
let mut new_remaining_views = Vec::new();
@@ -550,14 +557,39 @@ impl SlidingSync {
extensions: extensions.lock_mut().take().unwrap_or_default(), // extensions are sticky, we pop them here once
});
tracing::debug!("requesting");
let resp = client
.send_with_homeserver(req, None, self.homeserver.as_ref().map(ToString::to_string))
.await?;
let req = client.send_with_homeserver(req, None, self.homeserver.as_ref().map(ToString::to_string));
#[cfg(feature = "e2e-encryption")]
let resp_res = {
let (e2ee_uploads, resp) = futures_util::join!(client.send_outgoing_requests(), req);
if let Err(e) = e2ee_uploads {
tracing::error!(error = ?e, "Error while sending outgoing E2EE requests");
}
resp
};
#[cfg(not(feature = "e2e-encryption"))]
let resp_res = req.await;
let resp = match resp_res {
Ok(r) => r,
Err(e) => {
yield Err(e.into());
continue
}
};
tracing::debug!("received");
let updates = self.handle_response(resp, &remaining_views).await?;
let updates = match self.handle_response(resp, &remaining_views).await {
Ok(r) => r,
Err(e) => {
yield Err(e.into());
continue
}
};
tracing::debug!("handled");
yield updates;
yield Ok(updates);
}
})
}
@@ -878,7 +910,7 @@ impl SlidingSyncView {
}
#[tracing::instrument(skip(self, ops))]
fn room_ops(&self, ops: &Vec<v4::SyncOp>) -> anyhow::Result<()> {
fn room_ops(&self, ops: &Vec<v4::SyncOp>) -> Result<(), Error> {
let mut rooms_list = self.rooms_list.lock_mut();
let _rooms_map = self.rooms.lock_mut();
for op in ops {
@@ -886,9 +918,16 @@ impl SlidingSyncView {
v4::SlidingOp::Sync => {
let start: u32 = op
.range
.context("`range` must be present for Sync and Update operation")?
.ok_or_else(|| {
Error::BadResponse(
"`range` must be present for Sync and Update operation".to_owned(),
)
})?
.0
.try_into()?;
.try_into()
.map_err(|e| {
Error::BadResponse(format!("`range` not a valid int: {e:}"))
})?;
let room_ids = op.room_ids.clone();
room_ids
.into_iter()
@@ -902,21 +941,41 @@ impl SlidingSyncView {
v4::SlidingOp::Delete => {
let pos: u32 = op
.index
.context("`index` must be present for DELETE operation")?
.try_into()?;
.ok_or_else(|| {
Error::BadResponse(
"`index` must be present for DELETE operation".to_owned(),
)
})?
.try_into()
.map_err(|e| {
Error::BadResponse(format!(
"`index` not a valid int for DELETE: {:}",
e
))
})?;
rooms_list.set_cloned(pos as usize, RoomListEntry::Empty);
}
v4::SlidingOp::Insert => {
let pos: usize = op
.index
.context("`index` must be present for INSERT operation")?
.try_into()?;
.ok_or_else(|| {
Error::BadResponse(
"`index` must be present for INSERT operation".to_owned(),
)
})?
.try_into()
.map_err(|e| {
Error::BadResponse(format!(
"`index` not a valid int for INSERT: {:}",
e
))
})?;
let sliced = rooms_list.as_slice();
let room = RoomListEntry::Filled(
op.room_id
.clone()
.context("`room_id` must be present for INSERT operation")?,
);
let room = RoomListEntry::Filled(op.room_id.clone().ok_or_else(|| {
Error::BadResponse(
"`room_id` must be present for INSERT operation".to_owned(),
)
})?);
let mut dif = 0usize;
loop {
// find the next empty slot and drop it
@@ -925,7 +984,7 @@ impl SlidingSyncView {
let (next_p, overflown) = pos.overflowing_add(dif);
let check_after = !overflown && next_p < sliced.len();
if !check_prev && !check_after {
bail!("We were asked to insert but could not find any direction to shift to");
return Err(Error::BadResponse("We were asked to insert but could not find any direction to shift to".to_owned()));
}
if check_prev && sliced[prev_p].empty_or_invalidated() {
@@ -945,13 +1004,24 @@ impl SlidingSyncView {
v4::SlidingOp::Invalidate => {
let max_len = rooms_list.len();
let (mut pos, end): (u32, u32) = if let Some(range) = op.range {
(range.0.try_into()?, range.1.try_into()?)
(
range.0.try_into().map_err(|e| {
Error::BadResponse(format!("`range.0` not a valid int: {e:}"))
})?,
range.1.try_into().map_err(|e| {
Error::BadResponse(format!("`range.1` not a valid int: {e:}"))
})?,
)
} else {
bail!("`range` must be given on `Invalidate` operation")
return Err(Error::BadResponse(
"`range` must be given on `Invalidate` operation".to_owned(),
));
};
if pos > end {
bail!("Invalid invalidation, end smaller than start");
return Err(Error::BadResponse(
"Invalid invalidation, end smaller than start".to_owned(),
));
}
while pos < end {
@@ -983,7 +1053,7 @@ impl SlidingSyncView {
}
#[tracing::instrument(skip(self, ops))]
fn handle_response(&self, rooms_count: u32, ops: &Vec<v4::SyncOp>) -> anyhow::Result<bool> {
fn handle_response(&self, rooms_count: u32, ops: &Vec<v4::SyncOp>) -> Result<bool, Error> {
let mut missing =
rooms_count.checked_sub(self.rooms_list.lock_ref().len() as u32).unwrap_or_default();
let mut changed = false;

View File

@@ -13,8 +13,8 @@ test = false
[dependencies]
url = "2.2.2"
wasm-bindgen = { version = "0.2.74", features = ["serde-serialize"] }
wasm-bindgen-futures = "0.4.24"
wasm-bindgen = { version = "0.2.83" }
wasm-bindgen-futures = "0.4.33"
console_error_panic_hook = "0.1.6"
web-sys = { version = "0.3.51", features = ["console"] }
@@ -25,4 +25,4 @@ default-features = false
features = ["js", "native-tls", "e2e-encryption", "indexeddb"]
[dev-dependencies]
wasm-bindgen-test = "0.3.29"
wasm-bindgen-test = "0.3.33"

View File

@@ -22,10 +22,10 @@ serde_json = "1.0.85"
structopt = "0.3"
tokio = { version = "1", features = ["rt-multi-thread", "sync", "macros"] }
tracing-flame = "0.2"
tracing-subscriber = "0.3.15"
tracing-subscriber = "0.3.15"
tui-logger = "0.8.0"
tuirealm = "~1.7.1"
# file-logging specials
tracing = { version = "0.1.35", features = ["log"] }
log4rs = { version = " 1.1.1", default-features = false, features = ["file_appender"], optional = true }
log4rs = { version = "1.1.1", default-features = false, features = ["file_appender"], optional = true }

View File

@@ -30,4 +30,4 @@ serde_json = "1.0.79"
tokio = { version = "1.17.0", default-features = false, features = ["rt", "macros"] }
[target.'cfg(target_arch = "wasm32")'.dependencies]
wasm-bindgen-test = "0.3.30"
wasm-bindgen-test = "0.3.33"

View File

@@ -10,8 +10,8 @@ test = false
[dependencies]
camino = "1.0.8"
clap = { version = "3.2.4", features = ["derive"] }
clap = { version = "4.0.18", features = ["derive"] }
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79"
uniffi_bindgen = { workspace = true }
uniffi_bindgen = { workspace = true }
xshell = "0.1.17"

View File

@@ -18,31 +18,43 @@ const WASM_TIMEOUT_VALUE: &str = "120";
enum CiCommand {
/// Check style
Style,
/// Check for typos
Typos,
/// Check clippy lints
Clippy,
/// Check documentation
Docs,
/// Run tests with a specific feature set
TestFeatures {
#[clap(subcommand)]
cmd: Option<FeatureSet>,
},
/// Run tests for the appservice crate
TestAppservice,
/// Run checks for the wasm target
Wasm {
#[clap(subcommand)]
cmd: Option<WasmFeatureSet>,
},
/// Run wasm-pack tests
WasmPack {
#[clap(subcommand)]
cmd: Option<WasmFeatureSet>,
},
/// Run tests for the different crypto crate features
TestCrypto,
/// Check that bindings can be generated
Bindings,
/// Check that the examples compile
Examples,
}
@@ -91,6 +103,7 @@ impl CiArgs {
CiCommand::Wasm { cmd } => run_wasm_checks(cmd),
CiCommand::WasmPack { cmd } => run_wasm_pack_tests(cmd),
CiCommand::TestCrypto => run_crypto_tests(),
CiCommand::Bindings => check_bindings(),
CiCommand::Examples => check_examples(),
},
None => {
@@ -110,6 +123,34 @@ impl CiArgs {
}
}
fn check_bindings() -> Result<()> {
cmd!("rustup run stable cargo build -p matrix-sdk-crypto-ffi -p matrix-sdk-ffi").run()?;
cmd!(
"
uniffi-bindgen generate
--language kotlin
--language swift
--lib-file target/debug/libmatrix_sdk_ffi.a
--out-dir target/generated-bindings
bindings/matrix-sdk-ffi/src/api.udl
"
)
.run()?;
cmd!(
"
uniffi-bindgen generate
--language kotlin
--language swift
--lib-file target/debug/libmatrix_sdk_crypto_ffi.a
--out-dir target/generated-bindings
bindings/matrix-sdk-crypto-ffi/src/olm.udl
"
)
.run()?;
Ok(())
}
fn check_examples() -> Result<()> {
cmd!("rustup run stable cargo check -p example-*").run()?;
Ok(())