diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23e19225..ddb2ebbd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ '21', '24' ] + java: [ '21', '23' ] steps: - uses: actions/checkout@v4 @@ -30,7 +30,7 @@ jobs: with: dependency-graph: generate-and-submit - name: Install asciidoc - run: sudo apt update && sudo apt --no-install-recommends install -y asciidoc-base + run: sudo apt --no-install-recommends install -y asciidoc-base - name: Build with Gradle run: ./gradlew --no-daemon build - name: Build man page @@ -69,28 +69,3 @@ jobs: with: name: signal-cli-native path: build/native/nativeCompile/signal-cli - - build-client: - strategy: - matrix: - os: - - ubuntu - - macos - - windows - runs-on: ${{ matrix.os }}-latest - defaults: - run: - working-directory: ./client - steps: - - uses: actions/checkout@v4 - - name: Install rust - run: rustup default stable - - name: Build client - run: cargo build --release --verbose - - name: Archive production artifacts - uses: actions/upload-artifact@v4 - with: - name: signal-cli-client-${{ matrix.os }} - path: | - client/target/release/signal-cli-client - client/target/release/signal-cli-client.exe diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index f778268a..ff13469a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -35,7 +35,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@v2 # Override language selection by uncommenting this and choosing your languages # with: # languages: go, javascript, csharp, python, cpp, java @@ -43,7 +43,7 @@ jobs: # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@v2 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -57,4 +57,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b7ce03f1..b1f4027d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -182,7 +182,7 @@ jobs: tar xf ./"${ARCHIVE_DIR}"/*.tar.gz rm -r signal-cli-archive-* signal-cli-native mkdir -p build/install/ - mv ./signal-cli-"${GITHUB_REF_NAME#v}"/ build/install/signal-cli + mv ./signal-cli-*/ build/install/signal-cli - name: Build Image id: build_image diff --git a/CHANGELOG.md b/CHANGELOG.md index 74d0bdc0..e43ff34d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,73 +1,5 @@ # Changelog -## [Unreleased] - -## [0.13.18] - 2025-07-16 - -Requires libsignal-client version 0.76.3. - -### Added - -- Added `--view-once` parameter to send command to send view once images - -### Fixed - -- Handle rate limit exception correctly when querying usernames - -### Improved - -- Shut down when dbus daemon connection goes away unexpectedly -- In daemon mode, exit immediately if account check fails at startup -- Improve behavior when sending to devices that have no available prekeys - -## [0.13.17] - 2025-06-28 - -Requires libsignal-client version 0.76.0. - -### Fixed - -- Fix issue when loading an older inactive group -- Close attachment input streams after upload -- Fix storage sync behavior with unhandled fields - -### Changed - -- Improve behavior when pin data doesn't exist on the server - -## [0.13.16] - 2025-06-07 - -Requires libsignal-client version 0.73.2. - -### Changed - -- Ensure every sent message gets a unique timestamp - -## [0.13.15] - 2025-05-08 - -Requires libsignal-client version 0.70.0. - -### Fixed - -- Fix native access warning with Java 24 -- Fix storage sync loop due to old removed e164 field - -### Changed - -- Increased compatibility of native build with older/virtual CPUs - -## [0.13.14] - 2025-04-06 - -Requires libsignal-client version 0.68.1. - -### Fixed - -- Fix pre key import from old data files - -### Changed - -- Use websocket connection instead of HTTP for more requests -- Improve handling of messages with decryption error - ## [0.13.13] - 2025-02-28 Requires libsignal-client version 0.66.2. diff --git a/README.md b/README.md index c7228c09..e6d6e5ff 100644 --- a/README.md +++ b/README.md @@ -83,12 +83,6 @@ of all country codes.) signal-cli -a ACCOUNT send -m "This is a message" RECIPIENT ``` -* Send a message to a username, usernames need to be prefixed with `u:` - - ```sh - signal-cli -a ACCOUNT send -m "This is a message" u:USERNAME.000 - ``` - * Pipe the message content from another process. uname -a | signal-cli -a ACCOUNT send --message-from-stdin RECIPIENT diff --git a/build.gradle.kts b/build.gradle.kts index ea69d97e..4c4df536 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,12 +3,12 @@ plugins { application eclipse `check-lib-versions` - id("org.graalvm.buildtools.native") version "0.10.6" + id("org.graalvm.buildtools.native") version "0.10.5" } allprojects { group = "org.asamk" - version = "0.13.19-SNAPSHOT" + version = "0.13.13" } java { @@ -24,7 +24,6 @@ java { application { mainClass.set("org.asamk.signal.Main") - applicationDefaultJvmArgs = listOf("--enable-native-access=ALL-UNNAMED") } graalvmNative { @@ -33,7 +32,6 @@ graalvmNative { buildArgs.add("--install-exit-handlers") buildArgs.add("-Dfile.encoding=UTF-8") buildArgs.add("-J-Dfile.encoding=UTF-8") - buildArgs.add("-march=compatibility") resources.autodetect() configurationFileDirectories.from(file("graalvm-config-dir")) if (System.getenv("GRAALVM_HOME") == null) { @@ -48,41 +46,7 @@ graalvmNative { } } -val artifactType = Attribute.of("artifactType", String::class.java) -val minified = Attribute.of("minified", Boolean::class.javaObjectType) dependencies { - attributesSchema { - attribute(minified) - } - artifactTypes.getByName("jar") { - attributes.attribute(minified, false) - } -} - -configurations.runtimeClasspath.configure { - attributes { - attribute(minified, true) - } -} -val excludePatterns = mapOf( - "libsignal-client" to setOf( - "libsignal_jni_testing_amd64.so", - "signal_jni_testing_amd64.dll", - "libsignal_jni_testing_amd64.dylib", - "libsignal_jni_testing_aarch64.dylib", - ) -) - -dependencies { - registerTransform(JarFileExcluder::class) { - from.attribute(minified, false).attribute(artifactType, "jar") - to.attribute(minified, true).attribute(artifactType, "jar") - - parameters { - excludeFilesByArtifact = excludePatterns - } - } - implementation(libs.bouncycastle) implementation(libs.jackson.databind) implementation(libs.argparse4j) @@ -114,13 +78,12 @@ tasks.withType { attributes( "Implementation-Title" to project.name, "Implementation-Version" to project.version, - "Main-Class" to application.mainClass.get(), - "Enable-Native-Access" to "ALL-UNNAMED", + "Main-Class" to application.mainClass.get() ) } } -tasks.register("fatJar", type = Jar::class) { +task("fatJar", type = Jar::class) { archiveBaseName.set("${project.name}-fat") exclude( "META-INF/*.SF", @@ -129,11 +92,9 @@ tasks.register("fatJar", type = Jar::class) { "META-INF/NOTICE*", "META-INF/LICENSE*", "META-INF/INDEX.LIST", - "**/module-info.class", + "**/module-info.class" ) duplicatesStrategy = DuplicatesStrategy.WARN - doFirst { - from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) - } + from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) }) with(tasks.jar.get()) } diff --git a/buildSrc/src/main/kotlin/CheckLibVersionsPlugin.kt b/buildSrc/src/main/kotlin/CheckLibVersionsPlugin.kt index ae8ae4de..eb74acb2 100644 --- a/buildSrc/src/main/kotlin/CheckLibVersionsPlugin.kt +++ b/buildSrc/src/main/kotlin/CheckLibVersionsPlugin.kt @@ -1,10 +1,12 @@ @file:Suppress("DEPRECATION") +import groovy.util.XmlSlurper +import groovy.util.slurpersupport.GPathResult +import org.codehaus.groovy.runtime.ResourceGroovyMethods import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.Task import org.gradle.api.artifacts.Dependency -import javax.xml.parsers.DocumentBuilderFactory class CheckLibVersionsPlugin : Plugin { override fun apply(project: Project) { @@ -26,10 +28,10 @@ class CheckLibVersionsPlugin : Plugin { val name = dependency.name val metaDataUrl = "https://repo1.maven.org/maven2/$path/$name/maven-metadata.xml" try { - val dbf = DocumentBuilderFactory.newInstance() - val db = dbf.newDocumentBuilder() - val doc = db.parse(metaDataUrl); - val newest = doc.getElementsByTagName("latest").item(0).textContent + val url = ResourceGroovyMethods.toURL(metaDataUrl) + val metaDataText = ResourceGroovyMethods.getText(url) + val metadata = XmlSlurper().parseText(metaDataText) + val newest = (metadata.getProperty("versioning") as GPathResult).getProperty("latest") if (version != newest.toString()) { println("UPGRADE {\"group\": \"$group\", \"name\": \"$name\", \"current\": \"$version\", \"latest\": \"$newest\"}") } diff --git a/buildSrc/src/main/kotlin/ExcludeFileFromJar.kt b/buildSrc/src/main/kotlin/ExcludeFileFromJar.kt deleted file mode 100644 index 25862cc9..00000000 --- a/buildSrc/src/main/kotlin/ExcludeFileFromJar.kt +++ /dev/null @@ -1,53 +0,0 @@ -import org.gradle.api.artifacts.transform.* -import org.gradle.api.file.FileSystemLocation -import org.gradle.api.provider.Provider -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.PathSensitive -import org.gradle.api.tasks.PathSensitivity -import java.io.File -import java.io.FileInputStream -import java.io.FileOutputStream -import java.util.zip.ZipInputStream -import java.util.zip.ZipOutputStream - -@CacheableTransform -abstract class JarFileExcluder : TransformAction { - interface Parameters : TransformParameters { - @get:Input - var excludeFilesByArtifact: Map> - } - - @get:PathSensitive(PathSensitivity.NAME_ONLY) - @get:InputArtifact - abstract val inputArtifact: Provider - - override - fun transform(outputs: TransformOutputs) { - val fileName = inputArtifact.get().asFile.name - for (entry in parameters.excludeFilesByArtifact) { - if (fileName.startsWith(entry.key)) { - val nameWithoutExtension = fileName.substring(0, fileName.lastIndexOf(".")) - excludeFiles(inputArtifact.get().asFile, entry.value, outputs.file("${nameWithoutExtension}.jar")) - return - } - } - outputs.file(inputArtifact) - } - - private fun excludeFiles(artifact: File, excludeFiles: Set, jarFile: File) { - ZipInputStream(FileInputStream(artifact)).use { input -> - ZipOutputStream(FileOutputStream(jarFile)).use { output -> - var entry = input.nextEntry - while (entry != null) { - if (!excludeFiles.contains(entry.name)) { - output.putNextEntry(entry) - input.copyTo(output) - output.closeEntry() - } - - entry = input.nextEntry - } - } - } - } -} diff --git a/client/Cargo.lock b/client/Cargo.lock index 01f28e0c..b85be350 100644 --- a/client/Cargo.lock +++ b/client/Cargo.lock @@ -13,15 +13,15 @@ dependencies = [ [[package]] name = "adler2" -version = "2.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "anstream" -version = "0.6.19" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -34,50 +34,50 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.3" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.9" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", - "once_cell_polyfill", + "once_cell", "windows-sys 0.59.0", ] [[package]] name = "anyhow" -version = "1.0.98" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "async-trait" -version = "0.1.88" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", @@ -91,10 +91,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "backtrace" -version = "0.3.75" +name = "autocfg" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", "cfg-if", @@ -102,7 +108,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -113,21 +119,21 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "2.9.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" [[package]] name = "bytes" -version = "1.10.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "cc" -version = "1.2.29" +version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ "shlex", ] @@ -140,15 +146,15 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] name = "cfg-if" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.41" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9" +checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783" dependencies = [ "clap_builder", "clap_derive", @@ -156,9 +162,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.41" +version = "4.5.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d" +checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121" dependencies = [ "anstream", "anstyle", @@ -169,9 +175,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.41" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck", "proc-macro2", @@ -181,15 +187,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "colorchoice" -version = "1.0.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "combine" @@ -203,9 +209,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.10.1" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -230,18 +236,18 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.2" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -320,9 +326,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -337,9 +343,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "h2" -version = "0.4.11" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", @@ -356,9 +362,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.4" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -368,9 +374,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" -version = "1.3.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -389,12 +395,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http", "http-body", "pin-project-lite", @@ -402,15 +408,15 @@ dependencies = [ [[package]] name = "httparse" -version = "1.10.1" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "hyper" -version = "1.6.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", @@ -428,10 +434,11 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ + "futures-util", "http", "hyper", "hyper-util", @@ -445,18 +452,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.15" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", "hyper", - "libc", "pin-project-lite", "socket2", "tokio", @@ -466,22 +471,21 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ "displaydoc", - "potential_utf", "yoke", "zerofrom", "zerovec", ] [[package]] -name = "icu_locale_core" -version = "2.0.0" +name = "icu_locid" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" dependencies = [ "displaydoc", "litemap", @@ -491,10 +495,30 @@ dependencies = [ ] [[package]] -name = "icu_normalizer" -version = "2.0.0" +name = "icu_locid_transform" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" dependencies = [ "displaydoc", "icu_collections", @@ -502,54 +526,67 @@ dependencies = [ "icu_properties", "icu_provider", "smallvec", + "utf16_iter", + "utf8_iter", + "write16", "zerovec", ] [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" [[package]] name = "icu_properties" -version = "2.0.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" dependencies = [ "displaydoc", "icu_collections", - "icu_locale_core", + "icu_locid_transform", "icu_properties_data", "icu_provider", - "potential_utf", - "zerotrie", + "tinystr", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" [[package]] name = "icu_provider" -version = "2.0.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" dependencies = [ "displaydoc", - "icu_locale_core", + "icu_locid", + "icu_provider_macros", "stable_deref_trait", "tinystr", "writeable", "yoke", "zerofrom", - "zerotrie", "zerovec", ] +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "idna" version = "1.0.3" @@ -563,9 +600,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ "icu_normalizer", "icu_properties", @@ -573,25 +610,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.10.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", ] -[[package]] -name = "io-uring" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" -dependencies = [ - "bitflags", - "cfg-if", - "libc", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.1" @@ -600,24 +626,22 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jni" -version = "0.21.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" dependencies = [ "cesu8", - "cfg-if", "combine", "jni-sys", "log", "thiserror 1.0.69", "walkdir", - "windows-sys 0.45.0", ] [[package]] @@ -628,9 +652,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jsonrpsee" -version = "0.25.1" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fba77a59c4c644fd48732367624d1bcf6f409f9c9a286fbc71d2f1fc0b2ea16" +checksum = "c5c71d8c1a731cc4227c2f698d377e7848ca12c8a48866fc5e6951c43a4db843" dependencies = [ "jsonrpsee-core", "jsonrpsee-http-client", @@ -641,9 +665,9 @@ dependencies = [ [[package]] name = "jsonrpsee-core" -version = "0.25.1" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693c93cbb7db25f4108ed121304b671a36002c2db67dff2ee4391a688c738547" +checksum = "f2882f6f8acb9fdaec7cefc4fd607119a9bd709831df7d7672a1d3b644628280" dependencies = [ "async-trait", "bytes", @@ -657,19 +681,19 @@ dependencies = [ "rustc-hash", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 1.0.69", "tokio", "tokio-stream", - "tower", "tracing", ] [[package]] name = "jsonrpsee-http-client" -version = "0.25.1" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6962d2bd295f75e97dd328891e58fce166894b974c1f7ce2e7597f02eeceb791" +checksum = "b3638bc4617f96675973253b3a45006933bde93c2fd8a6170b33c777cc389e5b" dependencies = [ + "async-trait", "base64", "http-body", "hyper", @@ -681,17 +705,18 @@ dependencies = [ "rustls-platform-verifier", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 1.0.69", "tokio", "tower", + "tracing", "url", ] [[package]] name = "jsonrpsee-proc-macros" -version = "0.25.1" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fa4f5daed39f982a1bb9d15449a28347490ad42b212f8eaa2a2a344a0dce9e9" +checksum = "c06c01ae0007548e73412c08e2285ffe5d723195bf268bce67b1b77c3bb2a14d" dependencies = [ "heck", "proc-macro-crate", @@ -702,64 +727,92 @@ dependencies = [ [[package]] name = "jsonrpsee-types" -version = "0.25.1" +version = "0.24.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66df7256371c45621b3b7d2fb23aea923d577616b9c0e9c0b950a6ea5c2be0ca" +checksum = "a178c60086f24cc35bb82f57c651d0d25d99c4742b4d335de04e97fa1f08a8a1" dependencies = [ "http", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 1.0.69", ] [[package]] name = "libc" -version = "0.2.174" +version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" -version = "0.8.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "log" -version = "0.4.27" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.8.9" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.0.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "wasi", - "windows-sys 0.59.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", ] [[package]] @@ -773,21 +826,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.3" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "once_cell_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "percent-encoding" @@ -797,18 +844,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" dependencies = [ "proc-macro2", "quote", @@ -827,73 +874,65 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "potential_utf" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" -dependencies = [ - "zerovec", -] - [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.95" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.40" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] [[package]] name = "ring" -version = "0.17.14" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", "cfg-if", "getrandom", "libc", + "spin", "untrusted", "windows-sys 0.52.0", ] [[package]] name = "rustc-demangle" -version = "0.1.25" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustix" -version = "1.0.7" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ "bitflags", "errno", @@ -904,9 +943,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.29" +version = "0.23.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" dependencies = [ "log", "once_cell", @@ -919,30 +958,37 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ "openssl-probe", + "rustls-pemfile", "rustls-pki-types", "schannel", "security-framework", ] [[package]] -name = "rustls-pki-types" -version = "1.12.0" +name = "rustls-pemfile" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "zeroize", + "rustls-pki-types", ] [[package]] -name = "rustls-platform-verifier" -version = "0.5.3" +name = "rustls-pki-types" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19787cda76408ec5404443dc8b31795c87cd8fec49762dc75fa727740d34acc1" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" + +[[package]] +name = "rustls-platform-verifier" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" dependencies = [ "core-foundation", "core-foundation-sys", @@ -955,8 +1001,8 @@ dependencies = [ "rustls-webpki", "security-framework", "security-framework-sys", - "webpki-root-certs 0.26.11", - "windows-sys 0.59.0", + "webpki-roots", + "winapi", ] [[package]] @@ -967,9 +1013,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -978,9 +1024,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1002,14 +1048,15 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.2.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags", "core-foundation", "core-foundation-sys", "libc", + "num-bigint", "security-framework-sys", ] @@ -1025,18 +1072,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.217" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", @@ -1045,9 +1092,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.140" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -1070,35 +1117,45 @@ dependencies = [ "clap", "futures-util", "jsonrpsee", + "log", "serde", "serde_json", - "thiserror 2.0.12", + "thiserror 2.0.11", "tokio", "tokio-util", ] [[package]] name = "slab" -version = "0.4.10" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" -version = "1.15.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.10" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", "windows-sys 0.52.0", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1119,26 +1176,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.104" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" - [[package]] name = "synstructure" -version = "0.13.2" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", @@ -1147,9 +1198,9 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" +checksum = "5352447f921fda68cf61b4101566c0bdb5104eff6804d0678e5227580ab6a4e9" dependencies = [ "rustix", "windows-sys 0.59.0", @@ -1166,11 +1217,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.12" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" dependencies = [ - "thiserror-impl 2.0.12", + "thiserror-impl 2.0.11", ] [[package]] @@ -1186,9 +1237,9 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.12" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", @@ -1197,9 +1248,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ "displaydoc", "zerovec", @@ -1207,17 +1258,15 @@ dependencies = [ [[package]] name = "tokio" -version = "1.46.1" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", - "io-uring", "libc", "mio", "pin-project-lite", - "slab", "socket2", "tokio-macros", "windows-sys 0.52.0", @@ -1236,9 +1285,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ "rustls", "tokio", @@ -1257,9 +1306,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.15" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -1270,15 +1319,15 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.11" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.22.27" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "toml_datetime", @@ -1287,16 +1336,17 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.2" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", + "pin-project", "pin-project-lite", - "sync_wrapper", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -1317,6 +1367,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1324,9 +1375,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -1335,9 +1386,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", ] @@ -1350,9 +1401,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "untrusted" @@ -1371,6 +1422,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + [[package]] name = "utf8_iter" version = "1.0.4" @@ -1404,28 +1461,35 @@ dependencies = [ [[package]] name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] -name = "webpki-root-certs" -version = "0.26.11" +name = "webpki-roots" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75c7f0ef91146ebfb530314f5f1d24528d7f0767efbfd31dce919275413e393e" -dependencies = [ - "webpki-root-certs 1.0.1", -] - -[[package]] -name = "webpki-root-certs" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86138b15b2b7d561bc4469e77027b8dd005a43dc502e9031d1f5afc8ce1f280e" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.9" @@ -1436,13 +1500,10 @@ dependencies = [ ] [[package]] -name = "windows-sys" -version = "0.45.0" +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" @@ -1450,7 +1511,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets", ] [[package]] @@ -1459,31 +1520,7 @@ version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.2", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] @@ -1492,190 +1529,90 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows-targets" -version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - [[package]] name = "winnow" -version = "0.7.12" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] [[package]] -name = "writeable" -version = "0.6.1" +name = "write16" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yoke" -version = "0.8.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -1685,9 +1622,9 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", @@ -1697,18 +1634,18 @@ dependencies = [ [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", @@ -1722,22 +1659,11 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -[[package]] -name = "zerotrie" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", -] - [[package]] name = "zerovec" -version = "0.11.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" dependencies = [ "yoke", "zerofrom", @@ -1746,9 +1672,9 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", diff --git a/client/Cargo.toml b/client/Cargo.toml index aff9ede4..c435149f 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -1,17 +1,18 @@ [package] name = "signal-cli-client" version = "0.0.1" -edition = "2024" +edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] anyhow = "1" clap = { version = "4", features = ["cargo", "derive", "wrap_help"] } +log = "0.4" serde = "1" serde_json = "1" tokio = { version = "1", features = ["rt", "macros", "net", "rt-multi-thread"] } -jsonrpsee = { version = "0.25", features = [ +jsonrpsee = { version = "0.24", features = [ "macros", "async-client", "http-client", diff --git a/client/src/cli.rs b/client/src/cli.rs index 7fa5d1c5..4ff9d458 100644 --- a/client/src/cli.rs +++ b/client/src/cli.rs @@ -15,7 +15,6 @@ pub struct Cli { pub json_rpc_tcp: Option>, /// UNIX socket address and port of signal-cli daemon - #[cfg(unix)] #[arg(long, conflicts_with = "json_rpc_tcp")] pub json_rpc_socket: Option>, @@ -85,8 +84,6 @@ pub enum CliCommands { }, GetUserStatus { recipient: Vec, - #[arg(long)] - username: Vec, }, JoinGroup { #[arg(long)] @@ -179,9 +176,6 @@ pub enum CliCommands { #[arg(short = 'a', long)] attachment: Vec, - #[arg(long)] - view_once: bool, - #[arg(long)] mention: Vec, diff --git a/client/src/jsonrpc.rs b/client/src/jsonrpc.rs index 66ef9d9d..b085cde5 100644 --- a/client/src/jsonrpc.rs +++ b/client/src/jsonrpc.rs @@ -70,7 +70,6 @@ pub trait Rpc { &self, account: Option, recipients: Vec, - usernames: Vec, ) -> Result; #[method(name = "joinGroup", param_kind = map)] @@ -183,7 +182,6 @@ pub trait Rpc { endSession: bool, message: String, attachments: Vec, - viewOnce: bool, mentions: Vec, textStyle: Vec, quoteTimestamp: Option, @@ -192,10 +190,10 @@ pub trait Rpc { quoteMention: Vec, quoteTextStyle: Vec, quoteAttachment: Vec, - previewUrl: Option, - previewTitle: Option, - previewDescription: Option, - previewImage: Option, + preview_url: Option, + preview_title: Option, + preview_description: Option, + preview_image: Option, sticker: Option, storyTimestamp: Option, storyAuthor: Option, @@ -411,7 +409,6 @@ pub async fn connect_tcp( Ok(ClientBuilder::default().build_with_tokio(sender, receiver)) } -#[cfg(unix)] pub async fn connect_unix( socket_path: impl AsRef, ) -> Result { @@ -420,6 +417,6 @@ pub async fn connect_unix( Ok(ClientBuilder::default().build_with_tokio(sender, receiver)) } -pub async fn connect_http(uri: &str) -> Result, Error> { +pub async fn connect_http(uri: &str) -> Result { HttpClientBuilder::default().build(uri) } diff --git a/client/src/main.rs b/client/src/main.rs index ac12331d..35c1ab22 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -60,13 +60,8 @@ async fn handle_command( .delete_local_account_data(cli.account, ignore_registered) .await } - CliCommands::GetUserStatus { - recipient, - username, - } => { - client - .get_user_status(cli.account, recipient, username) - .await + CliCommands::GetUserStatus { recipient } => { + client.get_user_status(cli.account, recipient).await } CliCommands::JoinGroup { uri } => client.join_group(cli.account, uri).await, CliCommands::Link { name } => { @@ -75,7 +70,7 @@ async fn handle_command( .await .map_err(|e| RpcError::Custom(format!("JSON-RPC command startLink failed: {e:?}")))? .device_link_uri; - println!("{url}"); + println!("{}", url); client.finish_link(url, name).await } CliCommands::ListAccounts => client.list_accounts().await, @@ -144,7 +139,6 @@ async fn handle_command( end_session, message, attachment, - view_once, mention, text_style, quote_timestamp, @@ -171,7 +165,6 @@ async fn handle_command( end_session, message.unwrap_or_default(), attachment, - view_once, mention, text_style, quote_timestamp, @@ -484,30 +477,23 @@ async fn connect(cli: Cli) -> Result { handle_command(cli, client).await } else { - #[cfg(windows)] - { - Err(RpcError::Custom("Invalid socket".into())) - } - #[cfg(unix)] - { - let socket_path = cli - .json_rpc_socket - .clone() - .unwrap_or(None) - .or_else(|| { - std::env::var_os("XDG_RUNTIME_DIR").map(|runtime_dir| { - PathBuf::from(runtime_dir) - .join(DEFAULT_SOCKET_SUFFIX) - .into() - }) + let socket_path = cli + .json_rpc_socket + .clone() + .unwrap_or(None) + .or_else(|| { + std::env::var_os("XDG_RUNTIME_DIR").map(|runtime_dir| { + PathBuf::from(runtime_dir) + .join(DEFAULT_SOCKET_SUFFIX) + .into() }) - .unwrap_or_else(|| ("/run".to_owned() + DEFAULT_SOCKET_SUFFIX).into()); - let client = jsonrpc::connect_unix(socket_path) - .await - .map_err(|e| RpcError::Custom(format!("Failed to connect to socket: {e}")))?; + }) + .unwrap_or_else(|| ("/run".to_owned() + DEFAULT_SOCKET_SUFFIX).into()); + let client = jsonrpc::connect_unix(socket_path) + .await + .map_err(|e| RpcError::Custom(format!("Failed to connect to socket: {e}")))?; - handle_command(cli, client).await - } + handle_command(cli, client).await } } diff --git a/client/src/transports/mod.rs b/client/src/transports/mod.rs index ed1963a0..04f4390f 100644 --- a/client/src/transports/mod.rs +++ b/client/src/transports/mod.rs @@ -1,8 +1,10 @@ use futures_util::{stream::StreamExt, Sink, SinkExt, Stream}; -use jsonrpsee::core::client::{ReceivedMessage, TransportReceiverT, TransportSenderT}; +use jsonrpsee::core::{ + async_trait, + client::{ReceivedMessage, TransportReceiverT, TransportSenderT}, +}; use thiserror::Error; -#[cfg(unix)] pub mod ipc; mod stream_codec; pub mod tcp; @@ -19,6 +21,7 @@ struct Sender> { inner: T, } +#[async_trait] impl + Unpin + 'static> TransportSenderT for Sender { @@ -28,7 +31,7 @@ impl + Unpin + 'static> T self.inner .send(body) .await - .map_err(|e| Errors::Other(format!("{e:?}")))?; + .map_err(|e| Errors::Other(format!("{:?}", e)))?; Ok(()) } @@ -36,7 +39,7 @@ impl + Unpin + 'static> T self.inner .close() .await - .map_err(|e| Errors::Other(format!("{e:?}")))?; + .map_err(|e| Errors::Other(format!("{:?}", e)))?; Ok(()) } } @@ -45,6 +48,7 @@ struct Receiver { inner: T, } +#[async_trait] impl> + Unpin + 'static> TransportReceiverT for Receiver { @@ -54,7 +58,7 @@ impl> + Unpin + 'static> match self.inner.next().await { None => Err(Errors::Closed), Some(Ok(msg)) => Ok(ReceivedMessage::Text(msg)), - Some(Err(e)) => Err(Errors::Other(format!("{e:?}"))), + Some(Err(e)) => Err(Errors::Other(format!("{:?}", e))), } } } diff --git a/client/src/transports/stream_codec.rs b/client/src/transports/stream_codec.rs index e46233cb..6f77306f 100644 --- a/client/src/transports/stream_codec.rs +++ b/client/src/transports/stream_codec.rs @@ -41,7 +41,7 @@ impl Decoder for StreamCodec { match str::from_utf8(line.as_ref()) { Ok(s) => Ok(Some(s.to_string())), - Err(_) => Err(io::Error::other("invalid UTF-8")), + Err(_) => Err(io::Error::new(io::ErrorKind::Other, "invalid UTF-8")), } } else { Ok(None) diff --git a/data/org.asamk.SignalCli.metainfo.xml b/data/org.asamk.SignalCli.metainfo.xml index c6c07411..a0af7892 100644 --- a/data/org.asamk.SignalCli.metainfo.xml +++ b/data/org.asamk.SignalCli.metainfo.xml @@ -45,21 +45,6 @@ intense - - https://github.com/AsamK/signal-cli/releases/tag/v0.13.18 - - - https://github.com/AsamK/signal-cli/releases/tag/v0.13.17 - - - https://github.com/AsamK/signal-cli/releases/tag/v0.13.16 - - - https://github.com/AsamK/signal-cli/releases/tag/v0.13.15 - - - https://github.com/AsamK/signal-cli/releases/tag/v0.13.14 - https://github.com/AsamK/signal-cli/releases/tag/v0.13.13 diff --git a/graalvm-config-dir/jni-config.json b/graalvm-config-dir/jni-config.json index 523a6c03..7c68c6d6 100644 --- a/graalvm-config-dir/jni-config.json +++ b/graalvm-config-dir/jni-config.json @@ -27,10 +27,6 @@ { "name":"java.lang.ClassNotFoundException" }, -{ - "name":"java.lang.Enum", - "methods":[{"name":"ordinal","parameterTypes":[] }] -}, { "name":"java.lang.IllegalArgumentException", "methods":[{"name":"","parameterTypes":["java.lang.String"] }] @@ -52,13 +48,9 @@ { "name":"java.lang.String" }, -{ - "name":"java.lang.Thread", - "methods":[{"name":"currentThread","parameterTypes":[] }, {"name":"getStackTrace","parameterTypes":[] }] -}, { "name":"java.lang.Throwable", - "methods":[{"name":"getMessage","parameterTypes":[] }, {"name":"setStackTrace","parameterTypes":["java.lang.StackTraceElement[]"] }, {"name":"toString","parameterTypes":[] }] + "methods":[{"name":"getMessage","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }] }, { "name":"java.lang.UnsatisfiedLinkError", @@ -96,11 +88,7 @@ }, { "name":"org.signal.libsignal.internal.CompletableFuture", - "methods":[{"name":"","parameterTypes":[] }, {"name":"complete","parameterTypes":["java.lang.Object"] }, {"name":"completeExceptionally","parameterTypes":["java.lang.Throwable"] }, {"name":"setCancellationId","parameterTypes":["long"] }] -}, -{ - "name":"org.signal.libsignal.internal.NativeHandleGuard$SimpleOwner", - "methods":[{"name":"unsafeNativeHandleWithoutGuard","parameterTypes":[] }] + "methods":[{"name":"","parameterTypes":[] }, {"name":"complete","parameterTypes":["java.lang.Object"] }, {"name":"completeExceptionally","parameterTypes":["java.lang.Throwable"] }] }, { "name":"org.signal.libsignal.net.CdsiLookupResponse", @@ -126,10 +114,6 @@ "name":"org.signal.libsignal.net.NetworkException", "methods":[{"name":"","parameterTypes":["java.lang.String"] }] }, -{ - "name":"org.signal.libsignal.net.RetryLaterException", - "methods":[{"name":"","parameterTypes":["long"] }] -}, { "name":"org.signal.libsignal.protocol.DuplicateMessageException", "methods":[{"name":"","parameterTypes":["java.lang.String"] }] @@ -207,9 +191,6 @@ "name":"org.signal.libsignal.protocol.state.IdentityKeyStore$Direction", "fields":[{"name":"RECEIVING"}, {"name":"SENDING"}] }, -{ - "name":"org.signal.libsignal.protocol.state.IdentityKeyStore$IdentityChange" -}, { "name":"org.signal.libsignal.protocol.state.KyberPreKeyRecord", "fields":[{"name":"unsafeHandle"}] diff --git a/graalvm-config-dir/reflect-config.json b/graalvm-config-dir/reflect-config.json index 0bfd1cdf..481999d3 100644 --- a/graalvm-config-dir/reflect-config.json +++ b/graalvm-config-dir/reflect-config.json @@ -39,9 +39,6 @@ { "name":"[Ljava.sql.Statement;" }, -{ - "name":"[Lorg.asamk.signal.commands.ListStickerPacksCommand$JsonStickerPack$JsonSticker;" -}, { "name":"[Lorg.asamk.signal.json.JsonAttachment;" }, @@ -671,10 +668,6 @@ { "name":"long[]" }, -{ - "name":"okhttp3.internal.connection.RealConnectionPool", - "fields":[{"name":"addressStates"}] -}, { "name":"okio.BufferedSink" }, @@ -1413,12 +1406,6 @@ "name":"org.asamk.signal.manager.storage.profiles.LegacyProfileStore$ProfileStoreDeserializer", "methods":[{"name":"","parameterTypes":[] }] }, -{ - "name":"org.asamk.signal.manager.storage.profiles.LegacySignalProfile", - "allDeclaredFields":true, - "allDeclaredMethods":true, - "allDeclaredConstructors":true -}, { "name":"org.asamk.signal.manager.storage.profiles.LegacySignalProfileEntry", "allDeclaredFields":true, @@ -1630,10 +1617,6 @@ "name":"org.bouncycastle.jcajce.provider.asymmetric.NTRU$Mappings", "methods":[{"name":"","parameterTypes":[] }] }, -{ - "name":"org.bouncycastle.jcajce.provider.asymmetric.NoSig$Mappings", - "methods":[{"name":"","parameterTypes":[] }] -}, { "name":"org.bouncycastle.jcajce.provider.asymmetric.RSA$Mappings", "methods":[{"name":"","parameterTypes":[] }] @@ -2319,7 +2302,7 @@ "allDeclaredFields":true, "allDeclaredMethods":true, "allDeclaredConstructors":true, - "methods":[{"name":"getAnnouncementGroup","parameterTypes":[] }, {"name":"getAttachmentBackfill","parameterTypes":[] }, {"name":"getChangeNumber","parameterTypes":[] }, {"name":"getDeleteSync","parameterTypes":[] }, {"name":"getGiftBadges","parameterTypes":[] }, {"name":"getPaymentActivation","parameterTypes":[] }, {"name":"getPni","parameterTypes":[] }, {"name":"getSenderKey","parameterTypes":[] }, {"name":"getStorage","parameterTypes":[] }, {"name":"getStorageServiceEncryptionV2","parameterTypes":[] }, {"name":"getStories","parameterTypes":[] }, {"name":"getVersionedExpirationTimer","parameterTypes":[] }] + "methods":[{"name":"getAnnouncementGroup","parameterTypes":[] }, {"name":"getChangeNumber","parameterTypes":[] }, {"name":"getDeleteSync","parameterTypes":[] }, {"name":"getGiftBadges","parameterTypes":[] }, {"name":"getPaymentActivation","parameterTypes":[] }, {"name":"getPni","parameterTypes":[] }, {"name":"getSenderKey","parameterTypes":[] }, {"name":"getStorage","parameterTypes":[] }, {"name":"getStorageServiceEncryptionV2","parameterTypes":[] }, {"name":"getStories","parameterTypes":[] }, {"name":"getVersionedExpirationTimer","parameterTypes":[] }] }, { "name":"org.whispersystems.signalservice.api.account.ChangePhoneNumberRequest", @@ -2346,13 +2329,6 @@ { "name":"org.whispersystems.signalservice.api.groupsv2.TemporalCredential[]" }, -{ - "name":"org.whispersystems.signalservice.api.keys.OneTimePreKeyCounts", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":[] }] -}, { "name":"org.whispersystems.signalservice.api.link.LinkedDeviceVerificationCodeResponse", "allDeclaredFields":true, @@ -2420,14 +2396,7 @@ "name":"org.whispersystems.signalservice.api.profiles.SignalServiceProfileWrite", "allDeclaredFields":true, "allDeclaredMethods":true, - "allDeclaredConstructors":true, - "methods":[{"name":"","parameterTypes":["java.lang.String","byte[]","byte[]","byte[]","byte[]","byte[]","boolean","boolean","byte[]","java.util.List"] }, {"name":"getAbout","parameterTypes":[] }, {"name":"getAboutEmoji","parameterTypes":[] }, {"name":"getAvatar","parameterTypes":[] }, {"name":"getBadgeIds","parameterTypes":[] }, {"name":"getCommitment","parameterTypes":[] }, {"name":"getName","parameterTypes":[] }, {"name":"getPaymentAddress","parameterTypes":[] }, {"name":"getPhoneNumberSharing","parameterTypes":[] }, {"name":"getSameAvatar","parameterTypes":[] }, {"name":"getVersion","parameterTypes":[] }] -}, -{ - "name":"org.whispersystems.signalservice.api.provisioning.ProvisioningMessage", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true + "allDeclaredConstructors":true }, { "name":"org.whispersystems.signalservice.api.push.ServiceId", @@ -2472,12 +2441,6 @@ "queryAllDeclaredConstructors":true, "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String"] }] }, -{ - "name":"org.whispersystems.signalservice.api.ratelimit.SubmitRecaptchaChallengePayload", - "allDeclaredFields":true, - "queryAllDeclaredMethods":true, - "queryAllDeclaredConstructors":true -}, { "name":"org.whispersystems.signalservice.api.storage.StorageAuthResponse", "allDeclaredFields":true, @@ -3004,9 +2967,6 @@ "allDeclaredFields":true, "methods":[{"name":"adapter","parameterTypes":[] }, {"name":"unknownFields","parameterTypes":[] }] }, -{ - "name":"org.whispersystems.signalservice.internal.storage.protos.AccountRecord$BackupTierHistory" -}, { "name":"org.whispersystems.signalservice.internal.storage.protos.AccountRecord$Builder" }, @@ -3016,9 +2976,6 @@ { "name":"org.whispersystems.signalservice.internal.storage.protos.AccountRecord$IAPSubscriberData" }, -{ - "name":"org.whispersystems.signalservice.internal.storage.protos.AccountRecord$NotificationProfileManualOverride" -}, { "name":"org.whispersystems.signalservice.internal.storage.protos.AccountRecord$PhoneNumberSharingMode" }, @@ -3034,9 +2991,6 @@ "name":"org.whispersystems.signalservice.internal.storage.protos.AccountRecord$UsernameLink", "allDeclaredFields":true }, -{ - "name":"org.whispersystems.signalservice.internal.storage.protos.AvatarColor" -}, { "name":"org.whispersystems.signalservice.internal.storage.protos.ContactRecord", "allDeclaredFields":true, @@ -3070,7 +3024,6 @@ { "name":"org.whispersystems.signalservice.internal.storage.protos.GroupV2Record", "allDeclaredFields":true, - "fields":[{"name":"archived"}, {"name":"avatarColor"}, {"name":"blocked"}, {"name":"dontNotifyForMentionsIfMuted"}, {"name":"hideStory"}, {"name":"markedUnread"}, {"name":"masterKey"}, {"name":"mutedUntilTimestamp"}, {"name":"storySendMode"}, {"name":"whitelisted"}], "methods":[{"name":"adapter","parameterTypes":[] }, {"name":"unknownFields","parameterTypes":[] }] }, { diff --git a/graalvm-config-dir/resource-config.json b/graalvm-config-dir/resource-config.json index 8bd8a7af..b9ead797 100644 --- a/graalvm-config-dir/resource-config.json +++ b/graalvm-config-dir/resource-config.json @@ -188,6 +188,8 @@ "pattern":"\\Qlibsignal_jni_amd64.dylib\\E" }, { "pattern":"\\Qlibsignal_jni_amd64.so\\E" + }, { + "pattern":"\\Qlibsignal_jni_testing_amd64.so\\E" }, { "pattern":"\\Qorg/asamk/signal/manager/config/ias.store\\E" }, { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fec44a43..d0ac967c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,16 +2,16 @@ slf4j = "2.0.17" [libraries] -bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.81" -jackson-databind = "com.fasterxml.jackson.core:jackson-databind:2.19.1" +bouncycastle = "org.bouncycastle:bcprov-jdk18on:1.80" +jackson-databind = "com.fasterxml.jackson.core:jackson-databind:2.18.2" argparse4j = "net.sourceforge.argparse4j:argparse4j:0.9.0" dbusjava = "com.github.hypfvieh:dbus-java-transport-native-unixsocket:5.0.0" slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } slf4j-jul = { module = "org.slf4j:jul-to-slf4j", version.ref = "slf4j" } -logback = "ch.qos.logback:logback-classic:1.5.18" +logback = "ch.qos.logback:logback-classic:1.5.17" -signalservice = "com.github.turasa:signal-service-java:2.15.3_unofficial_127" -sqlite = "org.xerial:sqlite-jdbc:3.50.2.0" -hikari = "com.zaxxer:HikariCP:6.3.0" -junit-jupiter = "org.junit.jupiter:junit-jupiter:5.13.2" -junit-launcher = "org.junit.platform:junit-platform-launcher:1.13.2" +signalservice = "com.github.turasa:signal-service-java:2.15.3_unofficial_118" +sqlite = "org.xerial:sqlite-jdbc:3.49.1.0" +hikari = "com.zaxxer:HikariCP:6.2.1" +junit-jupiter = "org.junit.jupiter:junit-jupiter:5.12.0" +junit-launcher = "org.junit.platform:junit-platform-launcher:1.12.0" diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 8bdaf60c..a4b76b95 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 2a84e188..cea7a793 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index ef07e016..f3b75f3b 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright Š 2015 the original authors. +# Copyright Š 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH="\\\"\\\"" +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -205,7 +205,7 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. @@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + org.gradle.wrapper.GradleWrapperMain \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 5eed7ee8..9b42019c 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,11 @@ goto fail :execute @rem Setup the command line -set CLASSPATH= +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/lib/src/main/java/org/asamk/signal/manager/Manager.java b/lib/src/main/java/org/asamk/signal/manager/Manager.java index ccb661e1..bdb3dbc9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/Manager.java +++ b/lib/src/main/java/org/asamk/signal/manager/Manager.java @@ -1,7 +1,5 @@ package org.asamk.signal.manager; -import com.google.i18n.phonenumbers.PhoneNumberUtil; - import org.asamk.signal.manager.api.AlreadyReceivingException; import org.asamk.signal.manager.api.AttachmentInvalidException; import org.asamk.signal.manager.api.CaptchaRejectedException; @@ -30,7 +28,6 @@ import org.asamk.signal.manager.api.NotAGroupMemberException; import org.asamk.signal.manager.api.NotPrimaryDeviceException; import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.PendingAdminApprovalException; -import org.asamk.signal.manager.api.PinLockMissingException; import org.asamk.signal.manager.api.PinLockedException; import org.asamk.signal.manager.api.RateLimitException; import org.asamk.signal.manager.api.ReceiveConfig; @@ -52,6 +49,7 @@ import org.asamk.signal.manager.api.UsernameStatus; import org.asamk.signal.manager.api.VerificationMethodNotAvailableException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import java.io.Closeable; import java.io.File; @@ -67,7 +65,7 @@ import java.util.Set; public interface Manager extends Closeable { static boolean isValidNumber(final String e164Number, final String countryCode) { - return PhoneNumberUtil.getInstance().isPossibleNumber(e164Number, countryCode); + return PhoneNumberFormatter.isValidNumber(e164Number, countryCode); } static boolean isSignalClientAvailable() { @@ -96,7 +94,7 @@ public interface Manager extends Closeable { */ Map getUserStatus(Set numbers) throws IOException, RateLimitException; - Map getUsernameStatus(Set usernames) throws IOException; + Map getUsernameStatus(Set usernames); void updateAccountAttributes( String deviceName, @@ -141,7 +139,7 @@ public interface Manager extends Closeable { String newNumber, String verificationCode, String pin - ) throws IncorrectPinException, PinLockedException, IOException, NotPrimaryDeviceException, PinLockMissingException; + ) throws IncorrectPinException, PinLockedException, IOException, NotPrimaryDeviceException; void unregister() throws IOException; diff --git a/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java b/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java index 5f4f4463..7d358df6 100644 --- a/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java +++ b/lib/src/main/java/org/asamk/signal/manager/RegistrationManager.java @@ -3,7 +3,6 @@ package org.asamk.signal.manager; import org.asamk.signal.manager.api.CaptchaRequiredException; import org.asamk.signal.manager.api.IncorrectPinException; import org.asamk.signal.manager.api.NonNormalizedPhoneNumberException; -import org.asamk.signal.manager.api.PinLockMissingException; import org.asamk.signal.manager.api.PinLockedException; import org.asamk.signal.manager.api.RateLimitException; import org.asamk.signal.manager.api.VerificationMethodNotAvailableException; @@ -22,7 +21,7 @@ public interface RegistrationManager extends Closeable { void verifyAccount( String verificationCode, String pin - ) throws IOException, PinLockedException, IncorrectPinException, PinLockMissingException; + ) throws IOException, PinLockedException, IncorrectPinException; void deleteLocalAccountData() throws IOException; diff --git a/lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java b/lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java index cd0b5a21..4072a9df 100644 --- a/lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java +++ b/lib/src/main/java/org/asamk/signal/manager/SignalAccountFiles.java @@ -2,7 +2,6 @@ package org.asamk.signal.manager; import org.asamk.signal.manager.api.AccountCheckException; import org.asamk.signal.manager.api.NotRegisteredException; -import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.ServiceEnvironment; import org.asamk.signal.manager.config.ServiceConfig; import org.asamk.signal.manager.config.ServiceEnvironmentConfig; @@ -64,28 +63,19 @@ public class SignalAccountFiles { return accountsStore.getAllNumbers(); } - public MultiAccountManager initMultiAccountManager() throws IOException, AccountCheckException { - final var managerPairs = accountsStore.getAllAccounts().parallelStream().map(a -> { + public MultiAccountManager initMultiAccountManager() throws IOException { + final var managers = accountsStore.getAllAccounts().parallelStream().map(a -> { try { - return new Pair(initManager(a.number(), a.path()), null); - } catch (NotRegisteredException e) { + return initManager(a.number(), a.path()); + } catch (NotRegisteredException | IOException | AccountCheckException e) { logger.warn("Ignoring {}: {} ({})", a.number(), e.getMessage(), e.getClass().getSimpleName()); return null; - } catch (AccountCheckException | IOException e) { + } catch (Throwable e) { logger.error("Failed to load {}: {} ({})", a.number(), e.getMessage(), e.getClass().getSimpleName()); - return new Pair(null, e); + throw e; } }).filter(Objects::nonNull).toList(); - for (final var pair : managerPairs) { - if (pair.second() instanceof IOException e) { - throw e; - } else if (pair.second() instanceof AccountCheckException e) { - throw e; - } - } - - final var managers = managerPairs.stream().map(Pair::first).toList(); return new MultiAccountManagerImpl(managers, this); } diff --git a/lib/src/main/java/org/asamk/signal/manager/actions/RenewSessionAction.java b/lib/src/main/java/org/asamk/signal/manager/actions/RenewSessionAction.java index 35058940..40117246 100644 --- a/lib/src/main/java/org/asamk/signal/manager/actions/RenewSessionAction.java +++ b/lib/src/main/java/org/asamk/signal/manager/actions/RenewSessionAction.java @@ -19,7 +19,9 @@ public class RenewSessionAction implements HandleAction { @Override public void execute(Context context) throws Throwable { context.getAccount().getAccountData(accountId).getSessionStore().archiveSessions(serviceId); - context.getSendHelper().sendNullMessage(recipientId); + if (!recipientId.equals(context.getAccount().getSelfRecipientId())) { + context.getSendHelper().sendNullMessage(recipientId); + } } @Override diff --git a/lib/src/main/java/org/asamk/signal/manager/actions/SendRetryMessageRequestAction.java b/lib/src/main/java/org/asamk/signal/manager/actions/SendRetryMessageRequestAction.java index 96a94128..865f062f 100644 --- a/lib/src/main/java/org/asamk/signal/manager/actions/SendRetryMessageRequestAction.java +++ b/lib/src/main/java/org/asamk/signal/manager/actions/SendRetryMessageRequestAction.java @@ -7,6 +7,7 @@ import org.signal.libsignal.metadata.ProtocolException; import org.signal.libsignal.protocol.message.CiphertextMessage; import org.signal.libsignal.protocol.message.DecryptionErrorMessage; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.internal.push.Envelope; import java.util.Optional; @@ -14,21 +15,29 @@ import java.util.Optional; public class SendRetryMessageRequestAction implements HandleAction { private final RecipientId recipientId; + private final ServiceId serviceId; private final ProtocolException protocolException; private final SignalServiceEnvelope envelope; + private final ServiceId accountId; public SendRetryMessageRequestAction( final RecipientId recipientId, + final ServiceId serviceId, final ProtocolException protocolException, - final SignalServiceEnvelope envelope + final SignalServiceEnvelope envelope, + final ServiceId accountId ) { this.recipientId = recipientId; + this.serviceId = serviceId; this.protocolException = protocolException; this.envelope = envelope; + this.accountId = accountId; } @Override public void execute(Context context) throws Throwable { + context.getAccount().getAccountData(accountId).getSessionStore().archiveSessions(serviceId); + int senderDevice = protocolException.getSenderDevice(); Optional groupId = protocolException.getGroupId().isPresent() ? Optional.of(GroupId.unknownVersion( protocolException.getGroupId().get())) : Optional.empty(); diff --git a/lib/src/main/java/org/asamk/signal/manager/api/DeviceLinkUrl.java b/lib/src/main/java/org/asamk/signal/manager/api/DeviceLinkUrl.java index 2bb63507..54271dac 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/DeviceLinkUrl.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/DeviceLinkUrl.java @@ -2,6 +2,7 @@ package org.asamk.signal.manager.api; import org.asamk.signal.manager.util.Utils; import org.signal.libsignal.protocol.InvalidKeyException; +import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECPublicKey; import java.net.URI; @@ -36,7 +37,7 @@ public record DeviceLinkUrl(String deviceIdentifier, ECPublicKey deviceKey) { } ECPublicKey deviceKey; try { - deviceKey = new ECPublicKey(publicKeyBytes); + deviceKey = Curve.decodePoint(publicKeyBytes, 0); } catch (InvalidKeyException e) { throw new InvalidDeviceLinkException("Invalid device link", e); } diff --git a/lib/src/main/java/org/asamk/signal/manager/api/InvalidNumberException.java b/lib/src/main/java/org/asamk/signal/manager/api/InvalidNumberException.java index 14f37966..8e6a8064 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/InvalidNumberException.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/InvalidNumberException.java @@ -2,7 +2,7 @@ package org.asamk.signal.manager.api; public class InvalidNumberException extends Exception { - public InvalidNumberException(String message) { + InvalidNumberException(String message) { super(message); } diff --git a/lib/src/main/java/org/asamk/signal/manager/api/Message.java b/lib/src/main/java/org/asamk/signal/manager/api/Message.java index 9b372451..48277e6d 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/Message.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/Message.java @@ -6,7 +6,6 @@ import java.util.Optional; public record Message( String messageText, List attachments, - boolean viewOnce, List mentions, Optional quote, Optional sticker, diff --git a/lib/src/main/java/org/asamk/signal/manager/api/PinLockMissingException.java b/lib/src/main/java/org/asamk/signal/manager/api/PinLockMissingException.java deleted file mode 100644 index 7887d45f..00000000 --- a/lib/src/main/java/org/asamk/signal/manager/api/PinLockMissingException.java +++ /dev/null @@ -1,3 +0,0 @@ -package org.asamk.signal.manager.api; - -public class PinLockMissingException extends Exception {} diff --git a/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java b/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java index b1a3ad61..53da2aad 100644 --- a/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java +++ b/lib/src/main/java/org/asamk/signal/manager/api/RecipientIdentifier.java @@ -1,8 +1,8 @@ package org.asamk.signal.manager.api; -import org.asamk.signal.manager.util.PhoneNumberFormatter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import org.whispersystems.signalservice.api.util.UuidUtil; import java.util.UUID; @@ -24,28 +24,32 @@ public sealed interface RecipientIdentifier { sealed interface Single extends RecipientIdentifier { static Single fromString(String identifier, String localNumber) throws InvalidNumberException { - if (UuidUtil.isUuid(identifier)) { - return new Uuid(UUID.fromString(identifier)); - } - - if (identifier.startsWith("PNI:")) { - final var pni = identifier.substring(4); - if (!UuidUtil.isUuid(pni)) { - throw new InvalidNumberException("Invalid PNI"); + try { + if (UuidUtil.isUuid(identifier)) { + return new Uuid(UUID.fromString(identifier)); } - return new Pni(UUID.fromString(pni)); - } - if (identifier.startsWith("u:")) { - return new Username(identifier.substring(2)); - } + if (identifier.startsWith("PNI:")) { + final var pni = identifier.substring(4); + if (!UuidUtil.isUuid(pni)) { + throw new InvalidNumberException("Invalid PNI"); + } + return new Pni(UUID.fromString(pni)); + } - final var normalizedNumber = PhoneNumberFormatter.formatNumber(identifier, localNumber); - if (!normalizedNumber.equals(identifier)) { - final Logger logger = LoggerFactory.getLogger(RecipientIdentifier.class); - logger.debug("Normalized number {} to {}.", identifier, normalizedNumber); + if (identifier.startsWith("u:")) { + return new Username(identifier.substring(2)); + } + + final var normalizedNumber = PhoneNumberFormatter.formatNumber(identifier, localNumber); + if (!normalizedNumber.equals(identifier)) { + final Logger logger = LoggerFactory.getLogger(RecipientIdentifier.class); + logger.debug("Normalized number {} to {}.", identifier, normalizedNumber); + } + return new Number(normalizedNumber); + } catch (org.whispersystems.signalservice.api.util.InvalidNumberException e) { + throw new InvalidNumberException(e.getMessage(), e); } - return new Number(normalizedNumber); } static Single fromAddress(RecipientAddress address) { diff --git a/lib/src/main/java/org/asamk/signal/manager/config/LiveConfig.java b/lib/src/main/java/org/asamk/signal/manager/config/LiveConfig.java index c76da017..6a707fa5 100644 --- a/lib/src/main/java/org/asamk/signal/manager/config/LiveConfig.java +++ b/lib/src/main/java/org/asamk/signal/manager/config/LiveConfig.java @@ -2,9 +2,9 @@ package org.asamk.signal.manager.config; import org.signal.libsignal.net.Network.Environment; import org.signal.libsignal.protocol.InvalidKeyException; +import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECPublicKey; import org.whispersystems.signalservice.api.push.TrustStore; -import org.whispersystems.signalservice.internal.configuration.HttpProxy; import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl; import org.whispersystems.signalservice.internal.configuration.SignalCdsiUrl; import org.whispersystems.signalservice.internal.configuration.SignalProxy; @@ -28,9 +28,7 @@ class LiveConfig { private static final byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder() .decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF"); private static final String CDSI_MRENCLAVE = "0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57"; - private static final String SVR2_MRENCLAVE_LEGACY_LEGACY = "9314436a9a144992bb3680770ea5fd7934a7ffd29257844a33763a238903d570"; - private static final String SVR2_MRENCLAVE_LEGACY = "093be9ea32405e85ae28dbb48eb668aebeb7dbe29517b9b86ad4bec4dfe0e6a6"; - private static final String SVR2_MRENCLAVE = "29cd63c87bea751e3bfd0fbd401279192e2e5c99948b4ee9437eafc4968355fb"; + private static final String SVR2_MRENCLAVE = "9314436a9a144992bb3680770ea5fd7934a7ffd29257844a33763a238903d570"; private static final String URL = "https://chat.signal.org"; private static final String CDN_URL = "https://cdn.signal.org"; @@ -43,7 +41,6 @@ class LiveConfig { private static final Optional dns = Optional.empty(); private static final Optional proxy = Optional.empty(); - private static final Optional systemProxy = Optional.empty(); private static final byte[] zkGroupServerPublicParams = Base64.getDecoder() .decode("AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X36nOoGPs54XsEGzPdEV+itQNGUFEjY6X9Uv+Acuks7NpyGvCoKxGwgKgE5XyJ+nNKlyHHOLb6N1NuHyBrZrgtY/JYJHRooo5CEqYKBqdFnmbTVGEkCvJKxLnjwKWf+fEPoWeQFj5ObDjcKMZf2Jm2Ae69x+ikU5gBXsRmoF94GXTLfN0/vLt98KDPnxwAQL9j5V1jGOY8jQl6MLxEs56cwXN0dqCnImzVH3TZT1cJ8SW1BRX6qIVxEzjsSGx3yxF3suAilPMqGRp4ffyopjMD1JXiKR2RwLKzizUe5e8XyGOy9fplzhw3jVzTRyUZTRSZKkMLWcQ/gv0E4aONNqs4P+NameAZYOD12qRkxosQQP5uux6B2nRyZ7sAV54DgFyLiRcq1FvwKw2EPQdk4HDoePrO/RNUbyNddnM/mMgj4FW65xCoT1LmjrIjsv/Ggdlx46ueczhMgtBunx1/w8k8V+l8LVZ8gAT6wkU5J+DPQalQguMg12Jzug3q4TbdHiGCmD9EunCwOmsLuLJkz6EcSYXtrlDEnAM+hicw7iergYLLlMXpfTdGxJCWJmP4zqUFeTTmsmhsjGBt7NiEB/9pFFEB3pSbf4iiUukw63Eo8Aqnf4iwob6X1QviCWuc8t0LUlT9vALgh/f2DPVOOmR0RW6bgRvc7DSF20V/omg+YBw=="); @@ -71,7 +68,6 @@ class LiveConfig { interceptors, dns, proxy, - systemProxy, zkGroupServerPublicParams, genericServerPublicParams, backupServerPublicParams, @@ -80,7 +76,7 @@ class LiveConfig { static ECPublicKey getUnidentifiedSenderTrustRoot() { try { - return new ECPublicKey(UNIDENTIFIED_SENDER_TRUST_ROOT); + return Curve.decodePoint(UNIDENTIFIED_SENDER_TRUST_ROOT, 0); } catch (InvalidKeyException e) { throw new AssertionError(e); } @@ -92,7 +88,7 @@ class LiveConfig { createDefaultServiceConfiguration(interceptors), getUnidentifiedSenderTrustRoot(), CDSI_MRENCLAVE, - List.of(SVR2_MRENCLAVE, SVR2_MRENCLAVE_LEGACY, SVR2_MRENCLAVE_LEGACY_LEGACY)); + List.of(SVR2_MRENCLAVE)); } private LiveConfig() { diff --git a/lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java b/lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java index 587fc89b..fed6f457 100644 --- a/lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java +++ b/lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java @@ -30,8 +30,7 @@ public class ServiceConfig { public static AccountAttributes.Capabilities getCapabilities(boolean isPrimaryDevice) { final var deleteSync = !isPrimaryDevice; final var storageEncryptionV2 = !isPrimaryDevice; - final var attachmentBackfill = !isPrimaryDevice; - return new AccountAttributes.Capabilities(true, deleteSync, true, storageEncryptionV2, attachmentBackfill); + return new AccountAttributes.Capabilities(true, deleteSync, true, storageEncryptionV2); } public static ServiceEnvironmentConfig getServiceEnvironmentConfig( diff --git a/lib/src/main/java/org/asamk/signal/manager/config/StagingConfig.java b/lib/src/main/java/org/asamk/signal/manager/config/StagingConfig.java index e25fe21b..7eb04b3c 100644 --- a/lib/src/main/java/org/asamk/signal/manager/config/StagingConfig.java +++ b/lib/src/main/java/org/asamk/signal/manager/config/StagingConfig.java @@ -2,9 +2,9 @@ package org.asamk.signal.manager.config; import org.signal.libsignal.net.Network; import org.signal.libsignal.protocol.InvalidKeyException; +import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECPublicKey; import org.whispersystems.signalservice.api.push.TrustStore; -import org.whispersystems.signalservice.internal.configuration.HttpProxy; import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl; import org.whispersystems.signalservice.internal.configuration.SignalCdsiUrl; import org.whispersystems.signalservice.internal.configuration.SignalProxy; @@ -28,9 +28,7 @@ class StagingConfig { private static final byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder() .decode("BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx"); private static final String CDSI_MRENCLAVE = "0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57"; - private static final String SVR2_MRENCLAVE_LEGACY_LEGACY = "38e01eff4fe357dc0b0e8ef7a44b4abc5489fbccba3a78780f3872c277f62bf3"; - private static final String SVR2_MRENCLAVE_LEGACY = "2e8cefe6e3f389d8426adb24e9b7fb7adf10902c96f06f7bbcee36277711ed91"; - private static final String SVR2_MRENCLAVE = "a75542d82da9f6914a1e31f8a7407053b99cc99a0e7291d8fbd394253e19b036"; + private static final String SVR2_MRENCLAVE = "38e01eff4fe357dc0b0e8ef7a44b4abc5489fbccba3a78780f3872c277f62bf3"; private static final String URL = "https://chat.staging.signal.org"; private static final String CDN_URL = "https://cdn-staging.signal.org"; @@ -43,7 +41,6 @@ class StagingConfig { private static final Optional dns = Optional.empty(); private static final Optional proxy = Optional.empty(); - private static final Optional systemProxy = Optional.empty(); private static final byte[] zkGroupServerPublicParams = Base64.getDecoder() .decode("ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARBgELuMWWUEEfSK0mjXg+/2lPmWcTZWR9nkqgQQP0tbzuiPm74H2wMO4u1Wafe+UwyIlIT9L7KLS19Aw8r4sPrXZSSsOZ6s7M1+rTJN0bI5CKY2PX29y5Ok3jSWufIKcgKOnWoP67d5b2du2ZVJjpjfibNIHbT/cegy/sBLoFwtHogVYUewANUAXIaMPyCLRArsKhfJ5wBtTminG/PAvuBdJ70Z/bXVPf8TVsR292zQ65xwvWTejROW6AZX6aqucUjlENAErBme1YHmOSpU6tr6doJ66dPzVAWIanmO/5mgjNEDeK7DDqQdB1xd03HT2Qs2TxY3kCK8aAb/0iM0HQiXjxZ9HIgYhbtvGEnDKW5ILSUydqH/KBhW4Pb0jZWnqN/YgbWDKeJxnDbYcUob5ZY5Lt5ZCMKuaGUvCJRrCtuugSMaqjowCGRempsDdJEt+cMaalhZ6gczklJB/IbdwENW9KeVFPoFNFzhxWUIS5ML9riVYhAtE6JE5jX0xiHNVIIPthb458cfA8daR0nYfYAUKogQArm0iBezOO+mPk5vCNWI+wwkyFCqNDXz/qxl1gAntuCJtSfq9OC3NkdhQlgYQ=="); @@ -71,7 +68,6 @@ class StagingConfig { interceptors, dns, proxy, - systemProxy, zkGroupServerPublicParams, genericServerPublicParams, backupServerPublicParams, @@ -80,7 +76,7 @@ class StagingConfig { static ECPublicKey getUnidentifiedSenderTrustRoot() { try { - return new ECPublicKey(UNIDENTIFIED_SENDER_TRUST_ROOT); + return Curve.decodePoint(UNIDENTIFIED_SENDER_TRUST_ROOT, 0); } catch (InvalidKeyException e) { throw new AssertionError(e); } @@ -92,7 +88,7 @@ class StagingConfig { createDefaultServiceConfiguration(interceptors), getUnidentifiedSenderTrustRoot(), CDSI_MRENCLAVE, - List.of(SVR2_MRENCLAVE, SVR2_MRENCLAVE_LEGACY, SVR2_MRENCLAVE_LEGACY_LEGACY)); + List.of(SVR2_MRENCLAVE)); } private StagingConfig() { diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/AccountHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/AccountHelper.java index de3e2402..0710b50c 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/AccountHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/AccountHelper.java @@ -4,7 +4,6 @@ import org.asamk.signal.manager.api.CaptchaRequiredException; import org.asamk.signal.manager.api.DeviceLinkUrl; import org.asamk.signal.manager.api.IncorrectPinException; import org.asamk.signal.manager.api.NonNormalizedPhoneNumberException; -import org.asamk.signal.manager.api.PinLockMissingException; import org.asamk.signal.manager.api.PinLockedException; import org.asamk.signal.manager.api.RateLimitException; import org.asamk.signal.manager.api.VerificationMethodNotAvailableException; @@ -33,7 +32,6 @@ import org.whispersystems.signalservice.api.push.ServiceId.PNI; import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.SignedPreKeyEntity; -import org.whispersystems.signalservice.api.push.UsernameLinkComponents; import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException; import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException; @@ -52,7 +50,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Objects; -import java.util.UUID; +import java.util.Optional; import java.util.concurrent.TimeUnit; import okio.ByteString; @@ -106,7 +104,7 @@ public class AccountHelper { if (!account.isPrimaryDevice() && account.getPniIdentityKeyPair() == null) { throw new IOException("Missing PNI identity key, relinking required"); } - if (account.getPreviousStorageVersion() < 10 + if (account.getPreviousStorageVersion() < 4 && account.isPrimaryDevice() && account.getRegistrationLockPin() != null) { migrateRegistrationPin(); @@ -186,7 +184,7 @@ public class AccountHelper { String newNumber, String verificationCode, String pin - ) throws IncorrectPinException, PinLockedException, IOException, PinLockMissingException { + ) throws IncorrectPinException, PinLockedException, IOException { for (var attempts = 0; attempts < 5; attempts++) { try { finishChangeNumberInternal(newNumber, verificationCode, pin); @@ -206,7 +204,7 @@ public class AccountHelper { String newNumber, String verificationCode, String pin - ) throws IncorrectPinException, PinLockedException, IOException, PinLockMissingException { + ) throws IncorrectPinException, PinLockedException, IOException { final var pniIdentity = KeyUtils.generateIdentityKeyPair(); final var encryptedDeviceMessages = new ArrayList(); final var devicePniSignedPreKeys = new HashMap(); @@ -291,13 +289,12 @@ public class AccountHelper { context.getPinHelper(), (sessionId1, verificationCode1, registrationLock) -> { final var registrationApi = dependencies.getRegistrationApi(); - final var accountApi = dependencies.getAccountApi(); try { handleResponseException(registrationApi.verifyAccount(sessionId1, verificationCode1)); } catch (AlreadyVerifiedException e) { // Already verified so can continue changing number } - return handleResponseException(accountApi.changeNumber(new ChangePhoneNumberRequest(sessionId1, + return handleResponseException(registrationApi.changeNumber(new ChangePhoneNumberRequest(sessionId1, null, newNumber, registrationLock, @@ -381,7 +378,7 @@ public class AccountHelper { candidateHashes.add(Base64.encodeUrlSafeWithoutPadding(candidate.getHash())); } - final var response = handleResponseException(dependencies.getAccountApi().reserveUsername(candidateHashes)); + final var response = dependencies.getAccountManager().reserveUsername(candidateHashes); final var hashIndex = candidateHashes.indexOf(response.getUsernameHash()); if (hashIndex == -1) { logger.warn("[reserveUsername] The response hash could not be found in our set of candidateHashes."); @@ -391,7 +388,7 @@ public class AccountHelper { logger.debug("[reserveUsername] Successfully reserved username."); final var username = candidates.get(hashIndex); - final var linkComponents = confirmUsernameAndCreateNewLink(username); + final var linkComponents = dependencies.getAccountManager().confirmUsernameAndCreateNewLink(username); account.setUsername(username.getUsername()); account.setUsernameLink(linkComponents); account.getRecipientStore().resolveSelfRecipientTrusted(account.getSelfRecipientAddress()); @@ -399,40 +396,6 @@ public class AccountHelper { logger.debug("[confirmUsername] Successfully confirmed username."); } - public UsernameLinkComponents createUsernameLink(Username username) throws IOException { - try { - Username.UsernameLink link = username.generateLink(); - return handleResponseException(dependencies.getAccountApi().createUsernameLink(link)); - } catch (BaseUsernameException e) { - throw new AssertionError(e); - } - } - - private UsernameLinkComponents confirmUsernameAndCreateNewLink(Username username) throws IOException { - try { - Username.UsernameLink link = username.generateLink(); - UUID serverId = handleResponseException(dependencies.getAccountApi().confirmUsername(username, link)); - - return new UsernameLinkComponents(link.getEntropy(), serverId); - } catch (BaseUsernameException e) { - throw new AssertionError(e); - } - } - - private UsernameLinkComponents reclaimUsernameAndLink( - Username username, - UsernameLinkComponents linkComponents - ) throws IOException { - try { - Username.UsernameLink link = username.generateLink(linkComponents.getEntropy()); - UUID serverId = handleResponseException(dependencies.getAccountApi().confirmUsername(username, link)); - - return new UsernameLinkComponents(link.getEntropy(), serverId); - } catch (BaseUsernameException e) { - throw new AssertionError(e); - } - } - public void refreshCurrentUsername() throws IOException, BaseUsernameException { final var localUsername = account.getUsername(); if (localUsername == null) { @@ -475,14 +438,14 @@ public class AccountHelper { final var usernameLink = account.getUsernameLink(); if (usernameLink == null) { - handleResponseException(dependencies.getAccountApi() - .reserveUsername(List.of(Base64.encodeUrlSafeWithoutPadding(username.getHash())))); + dependencies.getAccountManager() + .reserveUsername(List.of(Base64.encodeUrlSafeWithoutPadding(username.getHash()))); logger.debug("[reserveUsername] Successfully reserved existing username."); - final var linkComponents = confirmUsernameAndCreateNewLink(username); + final var linkComponents = dependencies.getAccountManager().confirmUsernameAndCreateNewLink(username); account.setUsernameLink(linkComponents); logger.debug("[confirmUsername] Successfully confirmed existing username."); } else { - final var linkComponents = reclaimUsernameAndLink(username, usernameLink); + final var linkComponents = dependencies.getAccountManager().reclaimUsernameAndLink(username, usernameLink); account.setUsernameLink(linkComponents); logger.debug("[confirmUsername] Successfully reclaimed existing username and link."); } @@ -492,7 +455,7 @@ public class AccountHelper { private void tryToSetUsernameLink(Username username) { for (var i = 1; i < 4; i++) { try { - final var linkComponents = createUsernameLink(username); + final var linkComponents = dependencies.getAccountManager().createUsernameLink(username); account.setUsernameLink(linkComponents); break; } catch (IOException e) { @@ -502,8 +465,9 @@ public class AccountHelper { } public void deleteUsername() throws IOException { - handleResponseException(dependencies.getAccountApi().deleteUsername()); + dependencies.getAccountManager().deleteUsernameLink(); account.setUsernameLink(null); + dependencies.getAccountManager().deleteUsername(); account.setUsername(null); logger.debug("[deleteUsername] Successfully deleted the username."); } @@ -515,7 +479,7 @@ public class AccountHelper { } public void updateAccountAttributes() throws IOException { - handleResponseException(dependencies.getAccountApi().setAccountAttributes(account.getAccountAttributes(null))); + dependencies.getAccountManager().setAccountAttributes(account.getAccountAttributes(null)); } public void addDevice(DeviceLinkUrl deviceLinkInfo) throws IOException, org.asamk.signal.manager.api.DeviceLimitExceededException { @@ -536,9 +500,9 @@ public class AccountHelper { account.getAciIdentityKeyPair(), account.getPniIdentityKeyPair(), account.getProfileKey(), - account.getOrCreateAccountEntropyPool(), account.getOrCreatePinMasterKey(), account.getOrCreateMediaRootBackupKey(), + account.getOrCreateAccountEntropyPool(), verificationCode.getVerificationCode(), null)); account.setMultiDevice(true); @@ -546,8 +510,8 @@ public class AccountHelper { } public void removeLinkedDevices(int deviceId) throws IOException { - handleResponseException(dependencies.getLinkDeviceApi().removeDevice(deviceId)); - var devices = handleResponseException(dependencies.getLinkDeviceApi().getDevices()); + dependencies.getAccountManager().removeDevice(deviceId); + var devices = dependencies.getAccountManager().getDevices(); account.setMultiDevice(devices.size() > 1); } @@ -555,16 +519,14 @@ public class AccountHelper { var masterKey = account.getOrCreatePinMasterKey(); context.getPinHelper().migrateRegistrationLockPin(account.getRegistrationLockPin(), masterKey); - handleResponseException(dependencies.getAccountApi() - .enableRegistrationLock(masterKey.deriveRegistrationLock())); + dependencies.getAccountManager().enableRegistrationLock(masterKey); } public void setRegistrationPin(String pin) throws IOException { var masterKey = account.getOrCreatePinMasterKey(); context.getPinHelper().setRegistrationLockPin(pin, masterKey); - handleResponseException(dependencies.getAccountApi() - .enableRegistrationLock(masterKey.deriveRegistrationLock())); + dependencies.getAccountManager().enableRegistrationLock(masterKey); account.setRegistrationLockPin(pin); updateAccountAttributes(); @@ -573,7 +535,7 @@ public class AccountHelper { public void removeRegistrationPin() throws IOException { // Remove KBS Pin context.getPinHelper().removeRegistrationLockPin(); - handleResponseException(dependencies.getAccountApi().disableRegistrationLock()); + dependencies.getAccountManager().disableRegistrationLock(); account.setRegistrationLockPin(null); } @@ -582,7 +544,7 @@ public class AccountHelper { // When setting an empty GCM id, the Signal-Server also sets the fetchesMessages property to false. // If this is the primary device, other users can't send messages to this number anymore. // If this is a linked device, other users can still send messages, but this device doesn't receive them anymore. - handleResponseException(dependencies.getAccountApi().clearFcmToken()); + dependencies.getAccountManager().setGcmId(Optional.empty()); account.setRegistered(false); unregisteredListener.call(); @@ -596,7 +558,7 @@ public class AccountHelper { } account.setRegistrationLockPin(null); - handleResponseException(dependencies.getAccountApi().deleteAccount()); + dependencies.getAccountManager().deleteAccount(); account.setRegistered(false); unregisteredListener.call(); diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java index 08526c72..0ffa62ed 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/AttachmentHelper.java @@ -9,7 +9,6 @@ import org.asamk.signal.manager.util.IOUtils; import org.signal.libsignal.protocol.InvalidMessageException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.whispersystems.signalservice.api.crypto.AttachmentCipherInputStream; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentStream; @@ -45,20 +44,14 @@ public class AttachmentHelper { } public List uploadAttachments(final List attachments) throws AttachmentInvalidException, IOException { - final var attachmentStreams = createAttachmentStreams(attachments); + var attachmentStreams = createAttachmentStreams(attachments); - try { - // Upload attachments here, so we only upload once even for multiple recipients - final var attachmentPointers = new ArrayList(attachmentStreams.size()); - for (final var attachmentStream : attachmentStreams) { - attachmentPointers.add(uploadAttachment(attachmentStream)); - } - return attachmentPointers; - } finally { - for (final var attachmentStream : attachmentStreams) { - attachmentStream.close(); - } + // Upload attachments here, so we only upload once even for multiple recipients + var attachmentPointers = new ArrayList(attachmentStreams.size()); + for (var attachmentStream : attachmentStreams) { + attachmentPointers.add(uploadAttachment(attachmentStream)); } + return attachmentPointers; } private List createAttachmentStreams(List attachments) throws AttachmentInvalidException, IOException { @@ -139,15 +132,9 @@ public class AttachmentHelper { SignalServiceAttachmentPointer pointer, File tmpFile ) throws IOException { - if (pointer.getDigest().isEmpty()) { - throw new IOException("Attachment pointer has no digest."); - } try { return dependencies.getMessageReceiver() - .retrieveAttachment(pointer, - tmpFile, - ServiceConfig.MAX_ATTACHMENT_SIZE, - AttachmentCipherInputStream.IntegrityCheck.forEncryptedDigest(pointer.getDigest().get())); + .retrieveAttachment(pointer, tmpFile, ServiceConfig.MAX_ATTACHMENT_SIZE); } catch (MissingConfigurationException | InvalidMessageException e) { throw new IOException(e); } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java index 682bd996..0d838204 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/GroupHelper.java @@ -551,9 +551,6 @@ public class GroupHelper { while (true) { final var page = context.getGroupV2Helper() .getDecryptedGroupHistoryPage(groupSecretParams, fromRevision, sendEndorsementsExpirationMs); - if (page == null) { - break; - } page.getChangeLogs() .stream() .map(DecryptedGroupChangeLog::getChange) diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/GroupV2Helper.java b/lib/src/main/java/org/asamk/signal/manager/helper/GroupV2Helper.java index 8eb66843..900d7ea9 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/GroupV2Helper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/GroupV2Helper.java @@ -44,7 +44,6 @@ import org.whispersystems.signalservice.api.push.ServiceId.PNI; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; import org.whispersystems.signalservice.api.util.UuidUtil; -import org.whispersystems.signalservice.internal.push.exceptions.NotInGroupException; import java.io.IOException; import java.util.ArrayList; @@ -120,8 +119,6 @@ class GroupV2Helper { groupsV2AuthorizationString, false, sendEndorsementsExpirationMs); - } catch (NotInGroupException e) { - throw new NotAGroupMemberException(GroupUtils.getGroupIdV2(groupSecretParams), null); } catch (NonSuccessfulResponseCodeException e) { if (e.code == 403) { throw new NotAGroupMemberException(GroupUtils.getGroupIdV2(groupSecretParams), null); diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java b/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java index dd9cb38f..90d67a36 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/IncomingMessageHandler.java @@ -41,7 +41,6 @@ import org.signal.libsignal.metadata.ProtocolNoSessionException; import org.signal.libsignal.metadata.ProtocolUntrustedIdentityException; import org.signal.libsignal.metadata.SelfSendException; import org.signal.libsignal.protocol.InvalidMessageException; -import org.signal.libsignal.protocol.UsePqRatchet; import org.signal.libsignal.protocol.groups.GroupSessionBuilder; import org.signal.libsignal.protocol.message.DecryptionErrorMessage; import org.signal.libsignal.zkgroup.InvalidInputException; @@ -106,7 +105,7 @@ public final class IncomingMessageHandler { try { final var cipherResult = dependencies.getCipher(destination == null || destination.equals(account.getAci()) ? ServiceIdType.ACI : ServiceIdType.PNI) - .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp(), UsePqRatchet.NO); + .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp()); content = validate(envelope.getProto(), cipherResult, envelope.getServerDeliveredTimestamp()); if (content == null) { return new Pair<>(List.of(), null); @@ -144,7 +143,7 @@ public final class IncomingMessageHandler { try { final var cipherResult = dependencies.getCipher(destination == null || destination.equals(account.getAci()) ? ServiceIdType.ACI : ServiceIdType.PNI) - .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp(), UsePqRatchet.NO); + .decrypt(envelope.getProto(), envelope.getServerDeliveredTimestamp()); content = validate(envelope.getProto(), cipherResult, envelope.getServerDeliveredTimestamp()); if (content == null) { return new Pair<>(List.of(), null); @@ -158,9 +157,6 @@ public final class IncomingMessageHandler { } catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolNoSessionException | ProtocolInvalidMessageException e) { logger.debug("Failed to decrypt incoming message", e); - if (e instanceof ProtocolInvalidKeyIdException) { - actions.add(RefreshPreKeysAction.create()); - } final var sender = account.getRecipientResolver().resolveRecipient(e.getSender()); if (context.getContactHelper().isContactBlocked(sender)) { logger.debug("Received invalid message from blocked contact, ignoring."); @@ -169,11 +165,12 @@ public final class IncomingMessageHandler { if (serviceId != null) { final var isSelf = sender.equals(account.getSelfRecipientId()) && e.getSenderDevice() == account.getDeviceId(); - logger.debug("Received invalid message, queuing renew session action."); - actions.add(new RenewSessionAction(sender, serviceId, destination)); if (!isSelf) { logger.debug("Received invalid message, requesting message resend."); - actions.add(new SendRetryMessageRequestAction(sender, e, envelope)); + actions.add(new SendRetryMessageRequestAction(sender, serviceId, e, envelope, destination)); + } else { + logger.debug("Received invalid message, queuing renew session action."); + actions.add(new RenewSessionAction(sender, serviceId, destination)); } } else { logger.debug("Received invalid message from invalid sender: {}", e.getSender()); diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java index 40878647..a95635cf 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java @@ -88,11 +88,7 @@ public class PinHelper { IOException exception = null; for (final var secureValueRecovery : secureValueRecoveries) { try { - final var lockData = getRegistrationLockData(secureValueRecovery, svr2Credentials, pin); - if (lockData == null) { - continue; - } - return lockData; + return getRegistrationLockData(secureValueRecovery, svr2Credentials, pin); } catch (IOException e) { exception = e; } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/PreKeyHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/PreKeyHelper.java index bf7ad580..b17a9206 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/PreKeyHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/PreKeyHelper.java @@ -11,19 +11,17 @@ import org.signal.libsignal.protocol.state.PreKeyRecord; import org.signal.libsignal.protocol.state.SignedPreKeyRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.whispersystems.signalservice.api.NetworkResultUtil; import org.whispersystems.signalservice.api.account.PreKeyUpload; -import org.whispersystems.signalservice.api.keys.OneTimePreKeyCounts; import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; +import org.whispersystems.signalservice.internal.push.OneTimePreKeyCounts; import java.io.IOException; import java.util.List; import static org.asamk.signal.manager.config.ServiceConfig.PREKEY_STALE_AGE; import static org.asamk.signal.manager.config.ServiceConfig.SIGNED_PREKEY_ROTATE_AGE; -import static org.asamk.signal.manager.util.Utils.handleResponseException; public class PreKeyHelper { @@ -84,7 +82,7 @@ public class PreKeyHelper { ) throws IOException { OneTimePreKeyCounts preKeyCounts; try { - preKeyCounts = handleResponseException(dependencies.getKeysApi().getAvailablePreKeyCounts(serviceIdType)); + preKeyCounts = dependencies.getAccountManager().getPreKeyCounts(serviceIdType); } catch (AuthorizationFailedException e) { logger.debug("Failed to get pre key count, ignoring: " + e.getClass().getSimpleName()); preKeyCounts = new OneTimePreKeyCounts(0, 0); @@ -145,7 +143,7 @@ public class PreKeyHelper { kyberPreKeyRecords); var needsReset = false; try { - NetworkResultUtil.toPreKeysLegacy(dependencies.getKeysApi().setPreKeys(preKeyUpload)); + dependencies.getAccountManager().setPreKeys(preKeyUpload); try { if (preKeyRecords != null) { account.addPreKeys(serviceIdType, preKeyRecords); diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java index af16ed1d..0905bb30 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/ProfileHelper.java @@ -23,7 +23,6 @@ import org.signal.libsignal.zkgroup.profiles.ExpiringProfileKeyCredential; import org.signal.libsignal.zkgroup.profiles.ProfileKey; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.whispersystems.signalservice.api.NetworkResultUtil; import org.whispersystems.signalservice.api.crypto.SealedSenderAccess; import org.whispersystems.signalservice.api.profiles.AvatarUploadParams; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; @@ -197,10 +196,9 @@ public final class ProfileHelper { : avatar == null ? AvatarUploadParams.unchanged(true) : AvatarUploadParams.unchanged(false); final var paymentsAddress = Optional.ofNullable(newProfile.getMobileCoinAddress()) .map(address -> PaymentUtils.signPaymentsAddress(address, - account.getAciIdentityKeyPair().getPrivateKey())) - .orElse(null); + account.getAciIdentityKeyPair().getPrivateKey())); logger.debug("Uploading new profile"); - final var avatarPath = NetworkResultUtil.toSetProfileLegacy(dependencies.getProfileApi() + final var avatarPath = dependencies.getAccountManager() .setVersionedProfile(account.getAci(), account.getProfileKey(), newProfile.getInternalServiceName(), @@ -210,9 +208,9 @@ public final class ProfileHelper { avatarUploadParams, List.of(/* TODO implement support for badges */), account.getConfigurationStore().getPhoneNumberSharingMode() - == PhoneNumberSharingMode.EVERYBODY)); + == PhoneNumberSharingMode.EVERYBODY); if (!avatarUploadParams.keepTheSame) { - builder.withAvatarUrlPath(avatarPath); + builder.withAvatarUrlPath(avatarPath.orElse(null)); } newProfile = builder.build(); } diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java index 71f69081..ab75bd16 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/ReceiveHelper.java @@ -11,10 +11,10 @@ import org.asamk.signal.manager.storage.messageCache.CachedMessage; import org.asamk.signal.manager.storage.recipients.RecipientAddress; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.SignalWebSocket; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId.ACI; -import org.whispersystems.signalservice.api.websocket.SignalWebSocket; import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState; import org.whispersystems.signalservice.api.websocket.WebSocketUnavailableException; @@ -28,6 +28,7 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.TimeoutException; +import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.schedulers.Schedulers; public class ReceiveHelper { @@ -93,14 +94,14 @@ public class ReceiveHelper { // Use a Map here because java Set doesn't have a get method ... Map queuedActions = new HashMap<>(); - final var signalWebSocket = dependencies.getAuthenticatedSignalWebSocket(); - final var webSocketStateDisposable = signalWebSocket.getState() + final var signalWebSocket = dependencies.getSignalWebSocket(); + final var webSocketStateDisposable = Observable.merge(signalWebSocket.getUnidentifiedWebSocketState(), + signalWebSocket.getWebSocketState()) .subscribeOn(Schedulers.computation()) .observeOn(Schedulers.computation()) .distinctUntilChanged() .subscribe(this::onWebSocketStateChange); signalWebSocket.connect(); - signalWebSocket.registerKeepAliveToken("receive"); try { receiveMessagesInternal(signalWebSocket, timeout, returnOnTimeout, maxMessages, handler, queuedActions); @@ -108,7 +109,6 @@ public class ReceiveHelper { hasCaughtUpWithOldMessages = false; handleQueuedActions(queuedActions.keySet()); queuedActions.clear(); - signalWebSocket.removeKeepAliveToken("receive"); signalWebSocket.disconnect(); webSocketStateDisposable.dispose(); shouldStop = false; @@ -116,7 +116,7 @@ public class ReceiveHelper { } private void receiveMessagesInternal( - final SignalWebSocket.AuthenticatedWebSocket signalWebSocket, + final SignalWebSocket signalWebSocket, Duration timeout, boolean returnOnTimeout, Integer maxMessages, diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/RecipientHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/RecipientHelper.java index a73bb741..125fa0d8 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/RecipientHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/RecipientHelper.java @@ -10,14 +10,13 @@ import org.signal.libsignal.usernames.BaseUsernameException; import org.signal.libsignal.usernames.Username; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.whispersystems.signalservice.api.cds.CdsiV2Service; import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.push.ServiceId.PNI; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.CdsiInvalidArgumentException; import org.whispersystems.signalservice.api.push.exceptions.CdsiInvalidTokenException; -import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; +import org.whispersystems.signalservice.api.services.CdsiV2Service; import java.io.IOException; import java.util.Collection; @@ -26,10 +25,8 @@ import java.util.HashSet; import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.UUID; import static org.asamk.signal.manager.config.ServiceConfig.MAXIMUM_ONE_OFF_REQUEST_SIZE; -import static org.asamk.signal.manager.util.Utils.handleResponseException; public class RecipientHelper { @@ -69,7 +66,7 @@ public class RecipientHelper { .toSignalServiceAddress(); } - public Set resolveRecipients(Collection recipients) throws UnregisteredRecipientException, IOException { + public Set resolveRecipients(Collection recipients) throws UnregisteredRecipientException { final var recipientIds = new HashSet(recipients.size()); for (var number : recipients) { final var recipientId = resolveRecipient(number); @@ -79,11 +76,12 @@ public class RecipientHelper { } public RecipientId resolveRecipient(final RecipientIdentifier.Single recipient) throws UnregisteredRecipientException { - if (recipient instanceof RecipientIdentifier.Uuid(UUID uuid)) { - return account.getRecipientResolver().resolveRecipient(ACI.from(uuid)); - } else if (recipient instanceof RecipientIdentifier.Pni(UUID pni)) { - return account.getRecipientResolver().resolveRecipient(PNI.from(pni)); - } else if (recipient instanceof RecipientIdentifier.Number(String number)) { + if (recipient instanceof RecipientIdentifier.Uuid uuidRecipient) { + return account.getRecipientResolver().resolveRecipient(ACI.from(uuidRecipient.uuid())); + } else if (recipient instanceof RecipientIdentifier.Pni pniRecipient) { + return account.getRecipientResolver().resolveRecipient(PNI.from(pniRecipient.pni())); + } else if (recipient instanceof RecipientIdentifier.Number numberRecipient) { + final var number = numberRecipient.number(); return account.getRecipientStore().resolveRecipientByNumber(number, () -> { try { return getRegisteredUserByNumber(number); @@ -91,12 +89,9 @@ public class RecipientHelper { return null; } }); - } else if (recipient instanceof RecipientIdentifier.Username(String username)) { - try { - return resolveRecipientByUsernameOrLink(username, false); - } catch (Exception e) { - return null; - } + } else if (recipient instanceof RecipientIdentifier.Username usernameRecipient) { + var username = usernameRecipient.username(); + return resolveRecipientByUsernameOrLink(username, false); } throw new AssertionError("Unexpected RecipientIdentifier: " + recipient); } @@ -104,7 +99,7 @@ public class RecipientHelper { public RecipientId resolveRecipientByUsernameOrLink( String username, boolean forceRefresh - ) throws UnregisteredRecipientException, IOException { + ) throws UnregisteredRecipientException { final Username finalUsername; try { finalUsername = getUsernameFromUsernameOrLink(username); @@ -113,22 +108,18 @@ public class RecipientHelper { } if (forceRefresh) { try { - final var aci = handleResponseException(dependencies.getUsernameApi().getAciByUsername(finalUsername)); + final var aci = dependencies.getAccountManager().getAciByUsername(finalUsername); return account.getRecipientStore().resolveRecipientTrusted(aci, finalUsername.getUsername()); - } catch (NonSuccessfulResponseCodeException e) { - if (e.code == 404) { - throw new UnregisteredRecipientException(new org.asamk.signal.manager.api.RecipientAddress(null, - null, - null, - username)); - } - logger.debug("Failed to get uuid for username: {}", username, e); - throw e; + } catch (IOException e) { + throw new UnregisteredRecipientException(new org.asamk.signal.manager.api.RecipientAddress(null, + null, + null, + username)); } } return account.getRecipientStore().resolveRecipientByUsername(finalUsername.getUsername(), () -> { try { - return handleResponseException(dependencies.getUsernameApi().getAciByUsername(finalUsername)); + return dependencies.getAccountManager().getAciByUsername(finalUsername); } catch (Exception e) { return null; } @@ -139,8 +130,8 @@ public class RecipientHelper { try { final var usernameLinkUrl = UsernameLinkUrl.fromUri(username); final var components = usernameLinkUrl.getComponents(); - final var encryptedUsername = handleResponseException(dependencies.getUsernameApi() - .getEncryptedUsernameFromLinkServerId(components.getServerId())); + final var encryptedUsername = dependencies.getAccountManager() + .getEncryptedUsernameFromLinkServerId(components.getServerId()); final var link = new Username.UsernameLink(components.getEntropy(), encryptedUsername); return Username.fromLink(link); @@ -153,8 +144,8 @@ public class RecipientHelper { try { return Optional.of(resolveRecipient(recipient)); } catch (UnregisteredRecipientException e) { - if (recipient instanceof RecipientIdentifier.Number(String number)) { - return account.getRecipientStore().resolveRecipientByNumberOptional(number); + if (recipient instanceof RecipientIdentifier.Number r) { + return account.getRecipientStore().resolveRecipientByNumberOptional(r.number()); } else { return Optional.empty(); } @@ -243,8 +234,8 @@ public class RecipientHelper { final CdsiV2Service.Response response; try { - response = handleResponseException(dependencies.getCdsApi() - .getRegisteredUsers(token.isEmpty() ? Set.of() : previousNumbers, + response = dependencies.getAccountManager() + .getRegisteredUsersWithCdsi(token.isEmpty() ? Set.of() : previousNumbers, newNumbers, account.getRecipientStore().getServiceIdToProfileKeyMap(), token, @@ -265,7 +256,7 @@ public class RecipientHelper { account.setCdsiToken(newToken); account.setLastRecipientsRefresh(System.currentTimeMillis()); } - })); + }); } catch (CdsiInvalidTokenException | CdsiInvalidArgumentException e) { account.setCdsiToken(null); account.getCdsiStore().clearAll(); diff --git a/lib/src/main/java/org/asamk/signal/manager/helper/UnidentifiedAccessHelper.java b/lib/src/main/java/org/asamk/signal/manager/helper/UnidentifiedAccessHelper.java index cd2719a1..fb39789e 100644 --- a/lib/src/main/java/org/asamk/signal/manager/helper/UnidentifiedAccessHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/helper/UnidentifiedAccessHelper.java @@ -18,8 +18,6 @@ import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; -import static org.asamk.signal.manager.util.Utils.handleResponseException; - public class UnidentifiedAccessHelper { private static final Logger logger = LoggerFactory.getLogger(UnidentifiedAccessHelper.class); @@ -111,8 +109,7 @@ public class UnidentifiedAccessHelper { return privacySenderCertificate.getSerialized(); } try { - final var certificate = handleResponseException(dependencies.getCertificateApi() - .getSenderCertificateForPhoneNumberPrivacy()); + final var certificate = dependencies.getAccountManager().getSenderCertificateForPhoneNumberPrivacy(); privacySenderCertificate = new SenderCertificate(certificate); return certificate; } catch (IOException | InvalidCertificateException e) { @@ -128,7 +125,7 @@ public class UnidentifiedAccessHelper { return senderCertificate.getSerialized(); } try { - final var certificate = handleResponseException(dependencies.getCertificateApi().getSenderCertificate()); + final var certificate = dependencies.getAccountManager().getSenderCertificate(); this.senderCertificate = new SenderCertificate(certificate); return certificate; } catch (IOException | InvalidCertificateException e) { diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/ManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/internal/ManagerImpl.java index 726d0aaf..403b9adf 100644 --- a/lib/src/main/java/org/asamk/signal/manager/internal/ManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/internal/ManagerImpl.java @@ -35,7 +35,6 @@ import org.asamk.signal.manager.api.IdentityVerificationCode; import org.asamk.signal.manager.api.InactiveGroupLinkException; import org.asamk.signal.manager.api.IncorrectPinException; import org.asamk.signal.manager.api.InvalidDeviceLinkException; -import org.asamk.signal.manager.api.InvalidNumberException; import org.asamk.signal.manager.api.InvalidStickerException; import org.asamk.signal.manager.api.InvalidUsernameException; import org.asamk.signal.manager.api.LastGroupAdminException; @@ -48,7 +47,6 @@ import org.asamk.signal.manager.api.NotPrimaryDeviceException; import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.PendingAdminApprovalException; import org.asamk.signal.manager.api.PhoneNumberSharingMode; -import org.asamk.signal.manager.api.PinLockMissingException; import org.asamk.signal.manager.api.PinLockedException; import org.asamk.signal.manager.api.Profile; import org.asamk.signal.manager.api.RateLimitException; @@ -89,12 +87,12 @@ import org.asamk.signal.manager.storage.stickers.StickerPack; import org.asamk.signal.manager.util.AttachmentUtils; import org.asamk.signal.manager.util.KeyUtils; import org.asamk.signal.manager.util.MimeUtils; -import org.asamk.signal.manager.util.PhoneNumberFormatter; import org.asamk.signal.manager.util.StickerUtils; import org.signal.libsignal.protocol.InvalidMessageException; import org.signal.libsignal.usernames.BaseUsernameException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.SignalSessionLock; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServicePreview; @@ -108,6 +106,8 @@ import org.whispersystems.signalservice.api.push.exceptions.CdsiResourceExhauste import org.whispersystems.signalservice.api.push.exceptions.UsernameMalformedException; import org.whispersystems.signalservice.api.push.exceptions.UsernameTakenException; import org.whispersystems.signalservice.api.util.DeviceNameUtil; +import org.whispersystems.signalservice.api.util.InvalidNumberException; +import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import org.whispersystems.signalservice.api.util.StreamDetails; import org.whispersystems.signalservice.internal.util.Hex; import org.whispersystems.signalservice.internal.util.Util; @@ -132,7 +132,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -142,7 +142,6 @@ import io.reactivex.rxjava3.schedulers.Schedulers; import okio.Utf8; import static org.asamk.signal.manager.config.ServiceConfig.MAX_MESSAGE_SIZE_BYTES; -import static org.asamk.signal.manager.util.Utils.handleResponseException; import static org.signal.core.util.StringExtensionsKt.splitByByteLength; public class ManagerImpl implements Manager { @@ -162,7 +161,6 @@ public class ManagerImpl implements Manager { private final List closedListeners = new ArrayList<>(); private final List addressChangedListeners = new ArrayList<>(); private final CompositeDisposable disposable = new CompositeDisposable(); - private final AtomicLong lastMessageTimestamp = new AtomicLong(); public ManagerImpl( SignalAccount account, @@ -173,7 +171,15 @@ public class ManagerImpl implements Manager { ) { this.account = account; - final var sessionLock = new ReentrantSignalSessionLock(); + final var sessionLock = new SignalSessionLock() { + private final ReentrantLock LEGACY_LOCK = new ReentrantLock(); + + @Override + public Lock acquire() { + LEGACY_LOCK.lock(); + return LEGACY_LOCK::unlock; + } + }; this.dependencies = new SignalDependencies(serviceEnvironmentConfig, userAgent, account.getCredentialsProvider(), @@ -285,7 +291,7 @@ public class ManagerImpl implements Manager { } @Override - public Map getUsernameStatus(Set usernames) throws IOException { + public Map getUsernameStatus(Set usernames) { final var registeredUsers = new HashMap(); for (final var username : usernames) { try { @@ -429,7 +435,7 @@ public class ManagerImpl implements Manager { String newNumber, String verificationCode, String pin - ) throws IncorrectPinException, PinLockedException, IOException, NotPrimaryDeviceException, PinLockMissingException { + ) throws IncorrectPinException, PinLockedException, IOException, NotPrimaryDeviceException { if (!account.isPrimaryDevice()) { throw new NotPrimaryDeviceException(); } @@ -451,10 +457,10 @@ public class ManagerImpl implements Manager { String challenge, String captcha ) throws IOException, CaptchaRejectedException { - captcha = captcha == null ? "" : captcha.replace("signalcaptcha://", ""); + captcha = captcha == null ? null : captcha.replace("signalcaptcha://", ""); try { - handleResponseException(dependencies.getRateLimitChallengeApi().submitCaptchaChallenge(challenge, captcha)); + dependencies.getAccountManager().submitRateLimitRecaptchaChallenge(challenge, captcha); } catch (org.whispersystems.signalservice.internal.push.exceptions.CaptchaRejectedException ignored) { throw new CaptchaRejectedException(); } @@ -462,7 +468,7 @@ public class ManagerImpl implements Manager { @Override public List getLinkedDevices() throws IOException { - var devices = handleResponseException(dependencies.getLinkDeviceApi().getDevices()); + var devices = dependencies.getAccountManager().getDevices(); account.setMultiDevice(devices.size() > 1); var identityKey = account.getAciIdentityKeyPair().getPrivateKey(); return devices.stream().map(d -> { @@ -601,24 +607,6 @@ public class ManagerImpl implements Manager { return context.getGroupHelper().joinGroup(inviteLinkUrl); } - private long getNextMessageTimestamp() { - while (true) { - final var last = lastMessageTimestamp.get(); - final var timestamp = System.currentTimeMillis(); - if (last == timestamp) { - try { - Thread.sleep(1); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - continue; - } - if (lastMessageTimestamp.compareAndSet(last, timestamp)) { - return timestamp; - } - } - } - private SendMessageResults sendMessage( SignalServiceDataMessage.Builder messageBuilder, Set recipients, @@ -634,7 +622,7 @@ public class ManagerImpl implements Manager { Optional editTargetTimestamp ) throws IOException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException { var results = new HashMap>(); - long timestamp = getNextMessageTimestamp(); + long timestamp = System.currentTimeMillis(); messageBuilder.withTimestamp(timestamp); for (final var recipient : recipients) { if (recipient instanceof RecipientIdentifier.NoteToSelf || ( @@ -674,7 +662,7 @@ public class ManagerImpl implements Manager { Set recipients ) throws IOException, NotAGroupMemberException, GroupNotFoundException, GroupSendingNotAllowedException { var results = new HashMap>(); - final var timestamp = getNextMessageTimestamp(); + final var timestamp = System.currentTimeMillis(); for (var recipient : recipients) { if (recipient instanceof RecipientIdentifier.Single single) { final var message = new SignalServiceTypingMessage(action, timestamp, Optional.empty()); @@ -706,7 +694,7 @@ public class ManagerImpl implements Manager { @Override public SendMessageResults sendReadReceipt(RecipientIdentifier.Single sender, List messageIds) { - final var timestamp = getNextMessageTimestamp(); + final var timestamp = System.currentTimeMillis(); var receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.READ, messageIds, timestamp); @@ -716,7 +704,7 @@ public class ManagerImpl implements Manager { @Override public SendMessageResults sendViewedReceipt(RecipientIdentifier.Single sender, List messageIds) { - final var timestamp = getNextMessageTimestamp(); + final var timestamp = System.currentTimeMillis(); var receiptMessage = new SignalServiceReceiptMessage(SignalServiceReceiptMessage.Type.VIEWED, messageIds, timestamp); @@ -810,7 +798,6 @@ public class ManagerImpl implements Manager { } else if (!additionalAttachments.isEmpty()) { messageBuilder.withAttachments(additionalAttachments); } - messageBuilder.withViewOnce(message.viewOnce()); if (!message.mentions().isEmpty()) { messageBuilder.withMentions(resolveMentions(message.mentions())); } @@ -1607,8 +1594,7 @@ public class ManagerImpl implements Manager { context.close(); executor.close(); - dependencies.getAuthenticatedSignalWebSocket().disconnect(); - dependencies.getUnauthenticatedSignalWebSocket().disconnect(); + dependencies.getSignalWebSocket().disconnect(); dependencies.getPushServiceSocket().close(); disposable.dispose(); diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/ProvisioningManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/internal/ProvisioningManagerImpl.java index eeca842a..fcef536a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/internal/ProvisioningManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/internal/ProvisioningManagerImpl.java @@ -29,10 +29,12 @@ import org.asamk.signal.manager.util.KeyUtils; import org.signal.libsignal.protocol.IdentityKeyPair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.SignalServiceAccountManager; +import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations; +import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations; import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; -import org.whispersystems.signalservice.api.registration.ProvisioningApi; import org.whispersystems.signalservice.api.util.DeviceNameUtil; import org.whispersystems.signalservice.internal.push.ProvisioningSocket; import org.whispersystems.signalservice.internal.push.PushServiceSocket; @@ -56,7 +58,7 @@ public class ProvisioningManagerImpl implements ProvisioningManager { private final Consumer newManagerListener; private final AccountsStore accountsStore; - private final ProvisioningApi provisioningApi; + private final SignalServiceAccountManager accountManager; private final IdentityKeyPair tempIdentityKey; private final String password; @@ -75,6 +77,8 @@ public class ProvisioningManagerImpl implements ProvisioningManager { tempIdentityKey = KeyUtils.generateIdentityKeyPair(); password = KeyUtils.createPassword(); + final var clientZkOperations = ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration()); + final var groupsV2Operations = new GroupsV2Operations(clientZkOperations, ServiceConfig.GROUP_MAX_SIZE); final var credentialsProvider = new DynamicCredentialsProvider(null, null, null, @@ -83,22 +87,23 @@ public class ProvisioningManagerImpl implements ProvisioningManager { final var pushServiceSocket = new PushServiceSocket(serviceEnvironmentConfig.signalServiceConfiguration(), credentialsProvider, userAgent, + clientZkOperations.getProfileOperations(), ServiceConfig.AUTOMATIC_NETWORK_RETRY); - final var provisioningSocket = new ProvisioningSocket(serviceEnvironmentConfig.signalServiceConfiguration(), - userAgent); - this.provisioningApi = new ProvisioningApi(pushServiceSocket, provisioningSocket, credentialsProvider); + accountManager = new SignalServiceAccountManager(pushServiceSocket, + new ProvisioningSocket(serviceEnvironmentConfig.signalServiceConfiguration(), userAgent), + groupsV2Operations); } @Override public URI getDeviceLinkUri() throws TimeoutException, IOException { - var deviceUuid = provisioningApi.getNewDeviceUuid(); + var deviceUuid = accountManager.getNewDeviceUuid(); return new DeviceLinkUrl(deviceUuid, tempIdentityKey.getPublicKey().getPublicKey()).createDeviceLinkUri(); } @Override public String finishDeviceLink(String deviceName) throws IOException, TimeoutException, UserAlreadyExistsException { - var ret = provisioningApi.getNewDeviceRegistration(tempIdentityKey); + var ret = accountManager.getNewDeviceRegistration(tempIdentityKey); var number = ret.getNumber(); var aci = ret.getAci(); var pni = ret.getPni(); @@ -155,7 +160,7 @@ public class ProvisioningManagerImpl implements ProvisioningManager { final var pniPreKeys = generatePreKeysForType(account.getAccountData(ServiceIdType.PNI)); logger.debug("Finishing new device registration"); - var deviceId = provisioningApi.finishNewDeviceRegistration(ret.getProvisioningCode(), + var deviceId = accountManager.finishNewDeviceRegistration(ret.getProvisioningCode(), account.getAccountAttributes(null), aciPreKeys, pniPreKeys); diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/ReentrantSignalSessionLock.java b/lib/src/main/java/org/asamk/signal/manager/internal/ReentrantSignalSessionLock.java deleted file mode 100644 index 78304469..00000000 --- a/lib/src/main/java/org/asamk/signal/manager/internal/ReentrantSignalSessionLock.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.asamk.signal.manager.internal; - -import org.whispersystems.signalservice.api.SignalSessionLock; - -import java.util.concurrent.locks.ReentrantLock; - -class ReentrantSignalSessionLock implements SignalSessionLock { - - private final ReentrantLock LEGACY_LOCK = new ReentrantLock(); - - @Override - public Lock acquire() { - LEGACY_LOCK.lock(); - return LEGACY_LOCK::unlock; - } -} diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/RegistrationManagerImpl.java b/lib/src/main/java/org/asamk/signal/manager/internal/RegistrationManagerImpl.java index 72c4b63f..5faf1371 100644 --- a/lib/src/main/java/org/asamk/signal/manager/internal/RegistrationManagerImpl.java +++ b/lib/src/main/java/org/asamk/signal/manager/internal/RegistrationManagerImpl.java @@ -21,7 +21,6 @@ import org.asamk.signal.manager.RegistrationManager; import org.asamk.signal.manager.api.CaptchaRequiredException; import org.asamk.signal.manager.api.IncorrectPinException; import org.asamk.signal.manager.api.NonNormalizedPhoneNumberException; -import org.asamk.signal.manager.api.PinLockMissingException; import org.asamk.signal.manager.api.PinLockedException; import org.asamk.signal.manager.api.RateLimitException; import org.asamk.signal.manager.api.UpdateProfile; @@ -33,11 +32,14 @@ import org.asamk.signal.manager.helper.PinHelper; import org.asamk.signal.manager.storage.SignalAccount; import org.asamk.signal.manager.util.KeyUtils; import org.asamk.signal.manager.util.NumberVerificationUtils; +import org.asamk.signal.manager.util.Utils; import org.signal.libsignal.usernames.BaseUsernameException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.account.PreKeyCollection; +import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations; +import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations; import org.whispersystems.signalservice.api.kbs.MasterKey; import org.whispersystems.signalservice.api.push.ServiceId.ACI; import org.whispersystems.signalservice.api.push.ServiceId.PNI; @@ -46,13 +48,13 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException; import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException; import org.whispersystems.signalservice.api.svr.SecureValueRecovery; +import org.whispersystems.signalservice.internal.push.PushServiceSocket; import org.whispersystems.signalservice.internal.push.VerifyAccountResponse; import java.io.IOException; import java.util.function.Consumer; import static org.asamk.signal.manager.util.KeyUtils.generatePreKeysForType; -import static org.asamk.signal.manager.util.Utils.handleResponseException; public class RegistrationManagerImpl implements RegistrationManager { @@ -130,15 +132,12 @@ public class RegistrationManagerImpl implements RegistrationManager { } final var registrationApi = unauthenticatedAccountManager.getRegistrationApi(); - logger.trace("Creating verification session"); String sessionId = NumberVerificationUtils.handleVerificationSession(registrationApi, account.getSessionId(account.getNumber()), id -> account.setSessionId(account.getNumber(), id), voiceVerification, captcha); - logger.trace("Requesting verification code"); NumberVerificationUtils.requestVerificationCode(registrationApi, sessionId, voiceVerification); - logger.debug("Successfully requested verification code"); account.setRegistered(false); } catch (DeprecatedVersionException e) { logger.debug("Signal-Server returned deprecated version exception", e); @@ -150,7 +149,7 @@ public class RegistrationManagerImpl implements RegistrationManager { public void verifyAccount( String verificationCode, String pin - ) throws IOException, PinLockedException, IncorrectPinException, PinLockMissingException { + ) throws IOException, PinLockedException, IncorrectPinException { if (account.isRegistered()) { throw new IOException("Account is already registered"); } @@ -200,7 +199,7 @@ public class RegistrationManagerImpl implements RegistrationManager { final var aciPreKeys = generatePreKeysForType(account.getAccountData(ServiceIdType.ACI)); final var pniPreKeys = generatePreKeysForType(account.getAccountData(ServiceIdType.PNI)); final var registrationApi = unauthenticatedAccountManager.getRegistrationApi(); - final var response = handleResponseException(registrationApi.registerAccount(null, + final var response = Utils.handleResponseException(registrationApi.registerAccount(null, recoveryPassword, account.getAccountAttributes(null), aciPreKeys, @@ -222,14 +221,8 @@ public class RegistrationManagerImpl implements RegistrationManager { private boolean attemptReactivateAccount() { try { - final var dependencies = new SignalDependencies(serviceEnvironmentConfig, - userAgent, - account.getCredentialsProvider(), - account.getSignalServiceDataStore(), - null, - new ReentrantSignalSessionLock()); - handleResponseException(dependencies.getAccountApi() - .setAccountAttributes(account.getAccountAttributes(null))); + final var accountManager = createAuthenticatedSignalServiceAccountManager(); + accountManager.setAccountAttributes(account.getAccountAttributes(null)); account.setRegistered(true); logger.info("Reactivated existing account, verify is not necessary."); if (newManagerListener != null) { @@ -248,6 +241,17 @@ public class RegistrationManagerImpl implements RegistrationManager { return false; } + private SignalServiceAccountManager createAuthenticatedSignalServiceAccountManager() { + final var clientZkOperations = ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration()); + final var pushServiceSocket = new PushServiceSocket(serviceEnvironmentConfig.signalServiceConfiguration(), + account.getCredentialsProvider(), + userAgent, + clientZkOperations.getProfileOperations(), + ServiceConfig.AUTOMATIC_NETWORK_RETRY); + final var groupsV2Operations = new GroupsV2Operations(clientZkOperations, ServiceConfig.GROUP_MAX_SIZE); + return new SignalServiceAccountManager(pushServiceSocket, null, groupsV2Operations); + } + private VerifyAccountResponse verifyAccountWithCode( final String sessionId, final String verificationCode, @@ -257,11 +261,11 @@ public class RegistrationManagerImpl implements RegistrationManager { ) throws IOException { final var registrationApi = unauthenticatedAccountManager.getRegistrationApi(); try { - handleResponseException(registrationApi.verifyAccount(sessionId, verificationCode)); + Utils.handleResponseException(registrationApi.verifyAccount(sessionId, verificationCode)); } catch (AlreadyVerifiedException e) { // Already verified so can continue registering } - return handleResponseException(registrationApi.registerAccount(sessionId, + return Utils.handleResponseException(registrationApi.registerAccount(sessionId, null, account.getAccountAttributes(registrationLock), aciPreKeys, diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/SignalDependencies.java b/lib/src/main/java/org/asamk/signal/manager/internal/SignalDependencies.java index 0bc895cb..427c1025 100644 --- a/lib/src/main/java/org/asamk/signal/manager/internal/SignalDependencies.java +++ b/lib/src/main/java/org/asamk/signal/manager/internal/SignalDependencies.java @@ -5,7 +5,6 @@ import org.asamk.signal.manager.config.ServiceEnvironmentConfig; import org.asamk.signal.manager.util.Utils; import org.signal.libsignal.metadata.certificate.CertificateValidator; import org.signal.libsignal.net.Network; -import org.signal.libsignal.protocol.UsePqRatchet; import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,32 +13,26 @@ import org.whispersystems.signalservice.api.SignalServiceDataStore; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.SignalSessionLock; -import org.whispersystems.signalservice.api.account.AccountApi; -import org.whispersystems.signalservice.api.attachment.AttachmentApi; -import org.whispersystems.signalservice.api.cds.CdsApi; -import org.whispersystems.signalservice.api.certificate.CertificateApi; +import org.whispersystems.signalservice.api.SignalWebSocket; import org.whispersystems.signalservice.api.crypto.SignalServiceCipher; import org.whispersystems.signalservice.api.groupsv2.ClientZkOperations; import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api; import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations; -import org.whispersystems.signalservice.api.keys.KeysApi; import org.whispersystems.signalservice.api.link.LinkDeviceApi; -import org.whispersystems.signalservice.api.message.MessageApi; -import org.whispersystems.signalservice.api.profiles.ProfileApi; import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.SignalServiceAddress; -import org.whispersystems.signalservice.api.ratelimit.RateLimitChallengeApi; import org.whispersystems.signalservice.api.registration.RegistrationApi; import org.whispersystems.signalservice.api.services.ProfileService; import org.whispersystems.signalservice.api.storage.StorageServiceApi; import org.whispersystems.signalservice.api.storage.StorageServiceRepository; import org.whispersystems.signalservice.api.svr.SecureValueRecovery; -import org.whispersystems.signalservice.api.username.UsernameApi; import org.whispersystems.signalservice.api.util.CredentialsProvider; import org.whispersystems.signalservice.api.util.UptimeSleepTimer; -import org.whispersystems.signalservice.api.websocket.SignalWebSocket; +import org.whispersystems.signalservice.api.websocket.WebSocketFactory; +import org.whispersystems.signalservice.internal.push.ProvisioningSocket; import org.whispersystems.signalservice.internal.push.PushServiceSocket; import org.whispersystems.signalservice.internal.websocket.OkHttpWebSocketConnection; +import org.whispersystems.signalservice.internal.websocket.WebSocketConnection; import java.io.IOException; import java.net.InetSocketAddress; @@ -47,7 +40,6 @@ import java.net.Proxy; import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeUnit; import java.util.function.Supplier; public class SignalDependencies { @@ -66,31 +58,22 @@ public class SignalDependencies { private boolean allowStories = true; private SignalServiceAccountManager accountManager; - private AccountApi accountApi; - private RateLimitChallengeApi rateLimitChallengeApi; - private CdsApi cdsApi; - private UsernameApi usernameApi; private GroupsV2Api groupsV2Api; private RegistrationApi registrationApi; private LinkDeviceApi linkDeviceApi; private StorageServiceApi storageServiceApi; - private CertificateApi certificateApi; - private AttachmentApi attachmentApi; - private MessageApi messageApi; - private KeysApi keysApi; private GroupsV2Operations groupsV2Operations; private ClientZkOperations clientZkOperations; private PushServiceSocket pushServiceSocket; + private ProvisioningSocket provisioningSocket; private Network libSignalNetwork; - private SignalWebSocket.AuthenticatedWebSocket authenticatedSignalWebSocket; - private SignalWebSocket.UnauthenticatedWebSocket unauthenticatedSignalWebSocket; + private SignalWebSocket signalWebSocket; private SignalServiceMessageReceiver messageReceiver; private SignalServiceMessageSender messageSender; private List secureValueRecovery; private ProfileService profileService; - private ProfileApi profileApi; SignalDependencies( final ServiceEnvironmentConfig serviceEnvironmentConfig, @@ -120,12 +103,7 @@ public class SignalDependencies { this.registrationApi = null; this.secureValueRecovery = null; } - if (this.authenticatedSignalWebSocket != null) { - this.authenticatedSignalWebSocket.forceNewWebSocket(); - } - if (this.unauthenticatedSignalWebSocket != null) { - this.unauthenticatedSignalWebSocket.forceNewWebSocket(); - } + getSignalWebSocket().forceNewWebSockets(); } /** @@ -148,9 +126,16 @@ public class SignalDependencies { () -> pushServiceSocket = new PushServiceSocket(serviceEnvironmentConfig.signalServiceConfiguration(), credentialsProvider, userAgent, + getClientZkProfileOperations(), ServiceConfig.AUTOMATIC_NETWORK_RETRY)); } + public ProvisioningSocket getProvisioningSocket() { + return getOrCreate(() -> provisioningSocket, + () -> provisioningSocket = new ProvisioningSocket(getServiceEnvironmentConfig().signalServiceConfiguration(), + userAgent)); + } + public Network getLibSignalNetwork() { return getOrCreate(() -> libSignalNetwork, () -> { libSignalNetwork = new Network(serviceEnvironmentConfig.netEnvironment(), userAgent); @@ -184,9 +169,8 @@ public class SignalDependencies { public SignalServiceAccountManager getAccountManager() { return getOrCreate(() -> accountManager, - () -> accountManager = new SignalServiceAccountManager(getAuthenticatedSignalWebSocket(), - getAccountApi(), - getPushServiceSocket(), + () -> accountManager = new SignalServiceAccountManager(getPushServiceSocket(), + getProvisioningSocket(), getGroupsV2Operations())); } @@ -202,23 +186,6 @@ public class SignalDependencies { ServiceConfig.GROUP_MAX_SIZE); } - public AccountApi getAccountApi() { - return getOrCreate(() -> accountApi, () -> accountApi = new AccountApi(getAuthenticatedSignalWebSocket())); - } - - public RateLimitChallengeApi getRateLimitChallengeApi() { - return getOrCreate(() -> rateLimitChallengeApi, - () -> rateLimitChallengeApi = new RateLimitChallengeApi(getAuthenticatedSignalWebSocket())); - } - - public CdsApi getCdsApi() { - return getOrCreate(() -> cdsApi, () -> cdsApi = new CdsApi(getAuthenticatedSignalWebSocket())); - } - - public UsernameApi getUsernameApi() { - return getOrCreate(() -> usernameApi, () -> usernameApi = new UsernameApi(getUnauthenticatedSignalWebSocket())); - } - public GroupsV2Api getGroupsV2Api() { return getOrCreate(() -> groupsV2Api, () -> groupsV2Api = getAccountManager().getGroupsV2Api()); } @@ -228,41 +195,18 @@ public class SignalDependencies { } public LinkDeviceApi getLinkDeviceApi() { - return getOrCreate(() -> linkDeviceApi, - () -> linkDeviceApi = new LinkDeviceApi(getAuthenticatedSignalWebSocket())); + return getOrCreate(() -> linkDeviceApi, () -> linkDeviceApi = new LinkDeviceApi(getPushServiceSocket())); } private StorageServiceApi getStorageServiceApi() { return getOrCreate(() -> storageServiceApi, - () -> storageServiceApi = new StorageServiceApi(getAuthenticatedSignalWebSocket(), - getPushServiceSocket())); + () -> storageServiceApi = new StorageServiceApi(getPushServiceSocket())); } public StorageServiceRepository getStorageServiceRepository() { return new StorageServiceRepository(getStorageServiceApi()); } - public CertificateApi getCertificateApi() { - return getOrCreate(() -> certificateApi, - () -> certificateApi = new CertificateApi(getAuthenticatedSignalWebSocket())); - } - - public AttachmentApi getAttachmentApi() { - return getOrCreate(() -> attachmentApi, - () -> attachmentApi = new AttachmentApi(getAuthenticatedSignalWebSocket(), getPushServiceSocket())); - } - - public MessageApi getMessageApi() { - return getOrCreate(() -> messageApi, - () -> messageApi = new MessageApi(getAuthenticatedSignalWebSocket(), - getUnauthenticatedSignalWebSocket())); - } - - public KeysApi getKeysApi() { - return getOrCreate(() -> keysApi, - () -> keysApi = new KeysApi(getAuthenticatedSignalWebSocket(), getUnauthenticatedSignalWebSocket())); - } - public GroupsV2Operations getGroupsV2Operations() { return getOrCreate(() -> groupsV2Operations, () -> groupsV2Operations = new GroupsV2Operations(ClientZkOperations.create(serviceEnvironmentConfig.signalServiceConfiguration()), @@ -279,35 +223,33 @@ public class SignalDependencies { return clientZkOperations.getProfileOperations(); } - public SignalWebSocket.AuthenticatedWebSocket getAuthenticatedSignalWebSocket() { - return getOrCreate(() -> authenticatedSignalWebSocket, () -> { + public SignalWebSocket getSignalWebSocket() { + return getOrCreate(() -> signalWebSocket, () -> { final var timer = new UptimeSleepTimer(); final var healthMonitor = new SignalWebSocketHealthMonitor(timer); + final var webSocketFactory = new WebSocketFactory() { + @Override + public WebSocketConnection createWebSocket() { + return new OkHttpWebSocketConnection("normal", + serviceEnvironmentConfig.signalServiceConfiguration(), + Optional.of(credentialsProvider), + userAgent, + healthMonitor, + allowStories); + } - authenticatedSignalWebSocket = new SignalWebSocket.AuthenticatedWebSocket(() -> new OkHttpWebSocketConnection( - "normal", - serviceEnvironmentConfig.signalServiceConfiguration(), - Optional.of(credentialsProvider), - userAgent, - healthMonitor, - allowStories), () -> true, timer, TimeUnit.SECONDS.toMillis(10)); - healthMonitor.monitor(authenticatedSignalWebSocket); - }); - } - - public SignalWebSocket.UnauthenticatedWebSocket getUnauthenticatedSignalWebSocket() { - return getOrCreate(() -> unauthenticatedSignalWebSocket, () -> { - final var timer = new UptimeSleepTimer(); - final var healthMonitor = new SignalWebSocketHealthMonitor(timer); - - unauthenticatedSignalWebSocket = new SignalWebSocket.UnauthenticatedWebSocket(() -> new OkHttpWebSocketConnection( - "unidentified", - serviceEnvironmentConfig.signalServiceConfiguration(), - Optional.empty(), - userAgent, - healthMonitor, - allowStories), () -> true, timer, TimeUnit.SECONDS.toMillis(10)); - healthMonitor.monitor(unauthenticatedSignalWebSocket); + @Override + public WebSocketConnection createUnidentifiedWebSocket() { + return new OkHttpWebSocketConnection("unidentified", + serviceEnvironmentConfig.signalServiceConfiguration(), + Optional.empty(), + userAgent, + healthMonitor, + allowStories); + } + }; + signalWebSocket = new SignalWebSocket(webSocketFactory); + healthMonitor.monitor(signalWebSocket); }); } @@ -321,14 +263,10 @@ public class SignalDependencies { () -> messageSender = new SignalServiceMessageSender(getPushServiceSocket(), dataStore, sessionLock, - getAttachmentApi(), - getMessageApi(), - getKeysApi(), + getSignalWebSocket(), Optional.empty(), executor, - ServiceConfig.MAX_ENVELOPE_SIZE, - () -> true, - UsePqRatchet.NO)); + ServiceConfig.MAX_ENVELOPE_SIZE)); } public List getSecureValueRecovery() { @@ -339,19 +277,11 @@ public class SignalDependencies { .toList()); } - public ProfileApi getProfileApi() { - return getOrCreate(() -> profileApi, - () -> profileApi = new ProfileApi(getAuthenticatedSignalWebSocket(), - getUnauthenticatedSignalWebSocket(), - getPushServiceSocket(), - getClientZkProfileOperations())); - } - public ProfileService getProfileService() { return getOrCreate(() -> profileService, () -> profileService = new ProfileService(getClientZkProfileOperations(), - getAuthenticatedSignalWebSocket(), - getUnauthenticatedSignalWebSocket())); + getMessageReceiver(), + getSignalWebSocket())); } public SignalServiceCipher getCipher(ServiceIdType serviceIdType) { diff --git a/lib/src/main/java/org/asamk/signal/manager/internal/SignalWebSocketHealthMonitor.java b/lib/src/main/java/org/asamk/signal/manager/internal/SignalWebSocketHealthMonitor.java index 7d927ddd..0fb1585a 100644 --- a/lib/src/main/java/org/asamk/signal/manager/internal/SignalWebSocketHealthMonitor.java +++ b/lib/src/main/java/org/asamk/signal/manager/internal/SignalWebSocketHealthMonitor.java @@ -2,157 +2,195 @@ package org.asamk.signal.manager.internal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.whispersystems.signalservice.api.SignalWebSocket; import org.whispersystems.signalservice.api.util.Preconditions; import org.whispersystems.signalservice.api.util.SleepTimer; import org.whispersystems.signalservice.api.websocket.HealthMonitor; -import org.whispersystems.signalservice.api.websocket.SignalWebSocket; import org.whispersystems.signalservice.api.websocket.WebSocketConnectionState; import org.whispersystems.signalservice.internal.websocket.OkHttpWebSocketConnection; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; +import java.util.Arrays; import java.util.concurrent.TimeUnit; import io.reactivex.rxjava3.schedulers.Schedulers; -import kotlin.Unit; +/** + * Monitors the health of the identified and unidentified WebSockets. If either one appears to be + * unhealthy, will trigger restarting both. + *

+ * The monitor is also responsible for sending heartbeats/keep-alive messages to prevent + * timeouts. + */ final class SignalWebSocketHealthMonitor implements HealthMonitor { private static final Logger logger = LoggerFactory.getLogger(SignalWebSocketHealthMonitor.class); - /** - * This is the amount of time in between sent keep alives. Must be greater than [KEEP_ALIVE_TIMEOUT] - */ private static final long KEEP_ALIVE_SEND_CADENCE = TimeUnit.SECONDS.toMillis(OkHttpWebSocketConnection.KEEPALIVE_FREQUENCY_SECONDS); + private static final long MAX_TIME_SINCE_SUCCESSFUL_KEEP_ALIVE = KEEP_ALIVE_SEND_CADENCE * 3; - /** - * This is the amount of time we will wait for a response to the keep alive before we consider the websockets dead. - * It is required that this value be less than [KEEP_ALIVE_SEND_CADENCE] - */ - private static final long KEEP_ALIVE_TIMEOUT = TimeUnit.SECONDS.toMillis(20); - - private final Executor executor = Executors.newSingleThreadExecutor(); + private SignalWebSocket signalWebSocket; private final SleepTimer sleepTimer; - private SignalWebSocket webSocket = null; - private volatile KeepAliveSender keepAliveSender = null; - private boolean needsKeepAlive = false; - private long lastKeepAliveReceived = 0; + + private volatile KeepAliveSender keepAliveSender; + + private final HealthState identified = new HealthState(); + private final HealthState unidentified = new HealthState(); public SignalWebSocketHealthMonitor(SleepTimer sleepTimer) { this.sleepTimer = sleepTimer; } - void monitor(SignalWebSocket webSocket) { - Preconditions.checkNotNull(webSocket); - Preconditions.checkArgument(this.webSocket == null, "monitor can only be called once"); + public void monitor(SignalWebSocket signalWebSocket) { + Preconditions.checkNotNull(signalWebSocket); + Preconditions.checkArgument(this.signalWebSocket == null, "monitor can only be called once"); - executor.execute(() -> { + this.signalWebSocket = signalWebSocket; - this.webSocket = webSocket; + //noinspection ResultOfMethodCallIgnored + signalWebSocket.getWebSocketState() + .subscribeOn(Schedulers.computation()) + .observeOn(Schedulers.computation()) + .distinctUntilChanged() + .subscribe(s -> onStateChange(s, identified)); - webSocket.getState() - .subscribeOn(Schedulers.computation()) - .observeOn(Schedulers.computation()) - .distinctUntilChanged() - .subscribe(this::onStateChanged); - - webSocket.addKeepAliveChangeListener(() -> { - executor.execute(this::updateKeepAliveSenderStatus); - return Unit.INSTANCE; - }); - }); + //noinspection ResultOfMethodCallIgnored + signalWebSocket.getUnidentifiedWebSocketState() + .subscribeOn(Schedulers.computation()) + .observeOn(Schedulers.computation()) + .distinctUntilChanged() + .subscribe(s -> onStateChange(s, unidentified)); } - private void onStateChanged(WebSocketConnectionState connectionState) { - executor.execute(() -> { - needsKeepAlive = connectionState == WebSocketConnectionState.CONNECTED; + private synchronized void onStateChange(WebSocketConnectionState connectionState, HealthState healthState) { + switch (connectionState) { + case CONNECTED -> logger.debug("WebSocket is now connected"); + case AUTHENTICATION_FAILED -> logger.debug("WebSocket authentication failed"); + case FAILED -> logger.debug("WebSocket connection failed"); + } - updateKeepAliveSenderStatus(); - }); - } + healthState.needsKeepAlive = connectionState == WebSocketConnectionState.CONNECTED; - @Override - public void onKeepAliveResponse(long sentTimestamp, boolean isIdentifiedWebSocket) { - final var keepAliveTime = System.currentTimeMillis(); - executor.execute(() -> lastKeepAliveReceived = keepAliveTime); - } - - @Override - public void onMessageError(int status, boolean isIdentifiedWebSocket) { - } - - private void updateKeepAliveSenderStatus() { - if (keepAliveSender == null && sendKeepAlives()) { + if (keepAliveSender == null && isKeepAliveNecessary()) { keepAliveSender = new KeepAliveSender(); keepAliveSender.start(); - } else if (keepAliveSender != null && !sendKeepAlives()) { + } else if (keepAliveSender != null && !isKeepAliveNecessary()) { keepAliveSender.shutdown(); keepAliveSender = null; } } - private boolean sendKeepAlives() { - return needsKeepAlive && webSocket != null && webSocket.shouldSendKeepAlives(); + @Override + public void onKeepAliveResponse(long sentTimestamp, boolean isIdentifiedWebSocket) { + if (isIdentifiedWebSocket) { + identified.lastKeepAliveReceived = System.currentTimeMillis(); + } else { + unidentified.lastKeepAliveReceived = System.currentTimeMillis(); + } + } + + @Override + public void onMessageError(int status, boolean isIdentifiedWebSocket) { + if (status == 409) { + HealthState healthState = (isIdentifiedWebSocket ? identified : unidentified); + if (healthState.mismatchErrorTracker.addSample(System.currentTimeMillis())) { + logger.warn("Received too many mismatch device errors, forcing new websockets."); + signalWebSocket.forceNewWebSockets(); + signalWebSocket.connect(); + } + } + } + + private boolean isKeepAliveNecessary() { + return identified.needsKeepAlive || unidentified.needsKeepAlive; + } + + private static class HealthState { + + private final HttpErrorTracker mismatchErrorTracker = new HttpErrorTracker(5, TimeUnit.MINUTES.toMillis(1)); + + private volatile boolean needsKeepAlive; + private volatile long lastKeepAliveReceived; } /** - * Sends periodic heartbeats/keep-alives over the WebSocket to prevent connection timeouts. If - * the WebSocket fails to get a return heartbeat after [KEEP_ALIVE_TIMEOUT] seconds, it is forced to be recreated. + * Sends periodic heartbeats/keep-alives over both WebSockets to prevent connection timeouts. If + * either WebSocket fails 3 times to get a return heartbeat both are forced to be recreated. */ - private final class KeepAliveSender extends Thread { + private class KeepAliveSender extends Thread { private volatile boolean shouldKeepRunning = true; - @Override public void run() { - logger.debug("[KeepAliveSender({})] started", this.threadId()); - lastKeepAliveReceived = System.currentTimeMillis(); + identified.lastKeepAliveReceived = System.currentTimeMillis(); + unidentified.lastKeepAliveReceived = System.currentTimeMillis(); - var keepAliveSendTime = System.currentTimeMillis(); - while (shouldKeepRunning && sendKeepAlives()) { + while (shouldKeepRunning && isKeepAliveNecessary()) { try { - final var nextKeepAliveSendTime = keepAliveSendTime + KEEP_ALIVE_SEND_CADENCE; - sleepUntil(nextKeepAliveSendTime); + sleepTimer.sleep(KEEP_ALIVE_SEND_CADENCE); - if (shouldKeepRunning && sendKeepAlives()) { - keepAliveSendTime = System.currentTimeMillis(); - webSocket.sendKeepAlive(); - } + if (shouldKeepRunning && isKeepAliveNecessary()) { + long keepAliveRequiredSinceTime = System.currentTimeMillis() + - MAX_TIME_SINCE_SUCCESSFUL_KEEP_ALIVE; - final var responseRequiredTime = keepAliveSendTime + KEEP_ALIVE_TIMEOUT; - sleepUntil(responseRequiredTime); - - if (shouldKeepRunning && sendKeepAlives()) { - if (lastKeepAliveReceived < keepAliveSendTime) { - logger.debug("Missed keep alive, last: {} needed by: {}", - lastKeepAliveReceived, - responseRequiredTime); - webSocket.forceNewWebSocket(); + if (identified.lastKeepAliveReceived < keepAliveRequiredSinceTime + || unidentified.lastKeepAliveReceived < keepAliveRequiredSinceTime) { + logger.warn("Missed keep alives, identified last: " + + identified.lastKeepAliveReceived + + " unidentified last: " + + unidentified.lastKeepAliveReceived + + " needed by: " + + keepAliveRequiredSinceTime); + signalWebSocket.forceNewWebSockets(); + signalWebSocket.connect(); + } else { + signalWebSocket.sendKeepAlive(); } } } catch (Throwable e) { - logger.warn("Keep alive sender failed", e); - } - } - logger.debug("[KeepAliveSender({})] ended", threadId()); - } - - void sleepUntil(long timeMillis) { - while (System.currentTimeMillis() < timeMillis) { - final var waitTime = timeMillis - System.currentTimeMillis(); - if (waitTime > 0) { - try { - sleepTimer.sleep(waitTime); - } catch (InterruptedException e) { - logger.warn("WebSocket health monitor interrupted", e); - } + logger.warn("Error occurred in KeepAliveSender, ignoring ...", e); } } } - void shutdown() { + public void shutdown() { shouldKeepRunning = false; } } -} + private static final class HttpErrorTracker { + + private final long[] timestamps; + private final long errorTimeRange; + + public HttpErrorTracker(int samples, long errorTimeRange) { + this.timestamps = new long[samples]; + this.errorTimeRange = errorTimeRange; + } + + public synchronized boolean addSample(long now) { + long errorsMustBeAfter = now - errorTimeRange; + int count = 1; + int minIndex = 0; + + for (int i = 0; i < timestamps.length; i++) { + if (timestamps[i] < errorsMustBeAfter) { + timestamps[i] = 0; + } else if (timestamps[i] != 0) { + count++; + } + + if (timestamps[i] < timestamps[minIndex]) { + minIndex = i; + } + } + + timestamps[minIndex] = now; + + if (count >= timestamps.length) { + Arrays.fill(timestamps, 0); + return true; + } + return false; + } + } +} diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java index 83040906..4d43d15d 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/SignalAccount.java @@ -116,7 +116,7 @@ public class SignalAccount implements Closeable { private static final Logger logger = LoggerFactory.getLogger(SignalAccount.class); private static final int MINIMUM_STORAGE_VERSION = 1; - private static final int CURRENT_STORAGE_VERSION = 10; + private static final int CURRENT_STORAGE_VERSION = 9; private final Object LOCK = new Object(); @@ -827,7 +827,6 @@ public class SignalAccount implements Closeable { if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacyPreKeyStore() != null) { logger.debug("Migrating legacy pre key store."); - aciAccountData.getPreKeyStore().removeAllPreKeys(); for (var entry : legacySignalProtocolStore.getLegacyPreKeyStore().getPreKeys().entrySet()) { try { aciAccountData.getPreKeyStore().storePreKey(entry.getKey(), new PreKeyRecord(entry.getValue())); @@ -839,7 +838,6 @@ public class SignalAccount implements Closeable { if (legacySignalProtocolStore != null && legacySignalProtocolStore.getLegacySignedPreKeyStore() != null) { logger.debug("Migrating legacy signed pre key store."); - aciAccountData.getSignedPreKeyStore().removeAllSignedPreKeys(); for (var entry : legacySignalProtocolStore.getLegacySignedPreKeyStore().getSignedPreKeys().entrySet()) { try { aciAccountData.getSignedPreKeyStore() diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/accounts/AccountsStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/accounts/AccountsStore.java index 7be4a401..a0fa3012 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/accounts/AccountsStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/accounts/AccountsStore.java @@ -1,7 +1,6 @@ package org.asamk.signal.manager.storage.accounts; import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.i18n.phonenumbers.PhoneNumberUtil; import org.asamk.signal.manager.api.Pair; import org.asamk.signal.manager.api.ServiceEnvironment; @@ -11,6 +10,7 @@ import org.asamk.signal.manager.util.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.push.ServiceId.ACI; +import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -181,7 +181,7 @@ public class AccountsStore { return Arrays.stream(files) .filter(File::isFile) .map(File::getName) - .filter(file -> PhoneNumberUtil.getInstance().isPossibleNumber(file, null)) + .filter(file -> PhoneNumberFormatter.isValidNumber(file, null)) .collect(Collectors.toSet()); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java index a2d03a21..5e32ba12 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/identities/IdentityKeyStore.java @@ -8,7 +8,6 @@ import org.asamk.signal.manager.storage.recipients.RecipientStore; import org.signal.libsignal.protocol.IdentityKey; import org.signal.libsignal.protocol.InvalidKeyException; import org.signal.libsignal.protocol.state.IdentityKeyStore.Direction; -import org.signal.libsignal.protocol.state.IdentityKeyStore.IdentityChange; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.push.ServiceId; @@ -63,11 +62,11 @@ public class IdentityKeyStore { return identityChanges; } - public IdentityChange saveIdentity(final ServiceId serviceId, final IdentityKey identityKey) { + public boolean saveIdentity(final ServiceId serviceId, final IdentityKey identityKey) { return saveIdentity(serviceId.toString(), identityKey); } - public IdentityChange saveIdentity( + public boolean saveIdentity( final Connection connection, final ServiceId serviceId, final IdentityKey identityKey @@ -75,9 +74,9 @@ public class IdentityKeyStore { return saveIdentity(connection, serviceId.toString(), identityKey); } - IdentityChange saveIdentity(final String address, final IdentityKey identityKey) { + boolean saveIdentity(final String address, final IdentityKey identityKey) { if (isRetryingDecryption) { - return IdentityChange.NEW_OR_UNCHANGED; + return false; } try (final var connection = database.getConnection()) { return saveIdentity(connection, address, identityKey); @@ -86,24 +85,20 @@ public class IdentityKeyStore { } } - private IdentityChange saveIdentity( + private boolean saveIdentity( final Connection connection, final String address, final IdentityKey identityKey ) throws SQLException { final var identityInfo = loadIdentity(connection, address); - if (identityInfo == null) { - saveNewIdentity(connection, address, identityKey, true); - return IdentityChange.NEW_OR_UNCHANGED; - } - if (identityInfo.getIdentityKey().equals(identityKey)) { + if (identityInfo != null && identityInfo.getIdentityKey().equals(identityKey)) { // Identity already exists, not updating the trust level logger.trace("Not storing new identity for recipient {}, identity already stored", address); - return IdentityChange.NEW_OR_UNCHANGED; + return false; } - saveNewIdentity(connection, address, identityKey, false); - return IdentityChange.REPLACED_EXISTING; + saveNewIdentity(connection, address, identityKey, identityInfo == null); + return true; } public void setRetryingDecryption(final boolean retryingDecryption) { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/identities/SignalIdentityKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/identities/SignalIdentityKeyStore.java index 1ac7c9a6..5a1a676e 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/identities/SignalIdentityKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/identities/SignalIdentityKeyStore.java @@ -33,7 +33,7 @@ public class SignalIdentityKeyStore implements org.signal.libsignal.protocol.sta } @Override - public IdentityChange saveIdentity(SignalProtocolAddress address, IdentityKey identityKey) { + public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityKey) { return identityKeyStore.saveIdentity(address.getName(), identityKey); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java b/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java index e4fd8c01..51882a44 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/messageCache/MessageCache.java @@ -10,7 +10,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.nio.file.StandardCopyOption; import java.util.Arrays; import java.util.Collections; import java.util.Objects; @@ -76,7 +75,7 @@ public class MessageCache { return cachedMessage; } logger.debug("Moving cached message {} to {}", cachedMessage.getFile().toPath(), cacheFile.toPath()); - Files.move(cachedMessage.getFile().toPath(), cacheFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + Files.move(cachedMessage.getFile().toPath(), cacheFile.toPath()); return new CachedMessage(cacheFile); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/prekeys/PreKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/prekeys/PreKeyStore.java index 8e8bd2ab..d2d55710 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/prekeys/PreKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/prekeys/PreKeyStore.java @@ -4,9 +4,8 @@ import org.asamk.signal.manager.storage.Database; import org.asamk.signal.manager.storage.Utils; import org.signal.libsignal.protocol.InvalidKeyException; import org.signal.libsignal.protocol.InvalidKeyIdException; +import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECKeyPair; -import org.signal.libsignal.protocol.ecc.ECPrivateKey; -import org.signal.libsignal.protocol.ecc.ECPublicKey; import org.signal.libsignal.protocol.state.PreKeyRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -177,8 +176,8 @@ public class PreKeyStore implements SignalServicePreKeyStore { private PreKeyRecord getPreKeyRecordFromResultSet(ResultSet resultSet) throws SQLException { try { final var keyId = resultSet.getInt("key_id"); - final var publicKey = new ECPublicKey(resultSet.getBytes("public_key")); - final var privateKey = new ECPrivateKey(resultSet.getBytes("private_key")); + final var publicKey = Curve.decodePoint(resultSet.getBytes("public_key"), 0); + final var privateKey = Curve.decodePrivatePoint(resultSet.getBytes("private_key")); return new PreKeyRecord(keyId, new ECKeyPair(publicKey, privateKey)); } catch (InvalidKeyException e) { return null; diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/prekeys/SignedPreKeyStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/prekeys/SignedPreKeyStore.java index 4644c3ba..d62e939d 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/prekeys/SignedPreKeyStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/prekeys/SignedPreKeyStore.java @@ -4,9 +4,8 @@ import org.asamk.signal.manager.storage.Database; import org.asamk.signal.manager.storage.Utils; import org.signal.libsignal.protocol.InvalidKeyException; import org.signal.libsignal.protocol.InvalidKeyIdException; +import org.signal.libsignal.protocol.ecc.Curve; import org.signal.libsignal.protocol.ecc.ECKeyPair; -import org.signal.libsignal.protocol.ecc.ECPrivateKey; -import org.signal.libsignal.protocol.ecc.ECPublicKey; import org.signal.libsignal.protocol.state.SignedPreKeyRecord; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -239,8 +238,8 @@ public class SignedPreKeyStore implements org.signal.libsignal.protocol.state.Si private SignedPreKeyRecord getSignedPreKeyRecordFromResultSet(ResultSet resultSet) throws SQLException { try { final var keyId = resultSet.getInt("key_id"); - final var publicKey = new ECPublicKey(resultSet.getBytes("public_key")); - final var privateKey = new ECPrivateKey(resultSet.getBytes("private_key")); + final var publicKey = Curve.decodePoint(resultSet.getBytes("public_key"), 0); + final var privateKey = Curve.decodePrivatePoint(resultSet.getBytes("private_key")); final var signature = resultSet.getBytes("signature"); final var timestamp = resultSet.getLong("timestamp"); return new SignedPreKeyRecord(keyId, timestamp, new ECKeyPair(publicKey, privateKey), signature); diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/SignalProtocolStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/SignalProtocolStore.java index e1cf9a88..b631f632 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/protocol/SignalProtocolStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/protocol/SignalProtocolStore.java @@ -65,7 +65,7 @@ public class SignalProtocolStore implements SignalServiceAccountDataStore { } @Override - public IdentityChange saveIdentity(SignalProtocolAddress address, IdentityKey identityKey) { + public boolean saveIdentity(SignalProtocolAddress address, IdentityKey identityKey) { return identityKeyStore.saveIdentity(address, identityKey); } diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/MergeRecipientHelper.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/MergeRecipientHelper.java index 1454c8a7..0a96785b 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/MergeRecipientHelper.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/MergeRecipientHelper.java @@ -83,11 +83,10 @@ public class MergeRecipientHelper { recipientsToBeStripped.add(recipient); } - logger.debug("Got separate recipients for high trust identifiers {}, need to merge ({}, {}) and strip ({})", + logger.debug("Got separate recipients for high trust identifiers {}, need to merge ({}) and strip ({})", address, - resultingRecipient.map(RecipientWithAddress::address), - recipientsToBeMerged.stream().map(r -> r.address().toString()).collect(Collectors.joining(", ")), - recipientsToBeStripped.stream().map(r -> r.address().toString()).collect(Collectors.joining(", "))); + recipientsToBeMerged.stream().map(r -> r.id().toString()).collect(Collectors.joining(", ")), + recipientsToBeStripped.stream().map(r -> r.id().toString()).collect(Collectors.joining(", "))); RecipientAddress finalAddress = resultingRecipient.map(RecipientWithAddress::address).orElse(null); for (final var recipient : recipientsToBeMerged) { diff --git a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java index 442cbf4e..8d006416 100644 --- a/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java +++ b/lib/src/main/java/org/asamk/signal/manager/storage/recipients/RecipientStore.java @@ -994,12 +994,7 @@ public class RecipientStore implements RecipientIdCreator, RecipientResolver, Re ) throws SQLException { markUnregistered(connection, recipientId); final var address = resolveRecipientAddress(connection, recipientId); - final var needSplit = address.aci().isPresent() && address.pni().isPresent(); - logger.trace("Marking unregistered recipient {} as unregistered (and split={}): {}", - recipientId, - needSplit, - address); - if (needSplit) { + if (address.aci().isPresent() && address.pni().isPresent()) { final var numberAddress = new RecipientAddress(address.pni().get(), address.number().orElse(null)); updateRecipientAddress(connection, recipientId, address.removeIdentifiersFrom(numberAddress)); addNewRecipient(connection, numberAddress); diff --git a/lib/src/main/java/org/asamk/signal/manager/syncStorage/AccountRecordProcessor.java b/lib/src/main/java/org/asamk/signal/manager/syncStorage/AccountRecordProcessor.java index 30816060..656297bf 100644 --- a/lib/src/main/java/org/asamk/signal/manager/syncStorage/AccountRecordProcessor.java +++ b/lib/src/main/java/org/asamk/signal/manager/syncStorage/AccountRecordProcessor.java @@ -2,6 +2,7 @@ package org.asamk.signal.manager.syncStorage; import org.asamk.signal.manager.api.Profile; import org.asamk.signal.manager.internal.JobExecutor; +import org.asamk.signal.manager.jobs.CheckWhoAmIJob; import org.asamk.signal.manager.jobs.DownloadProfileAvatarJob; import org.asamk.signal.manager.storage.SignalAccount; import org.asamk.signal.manager.util.KeyUtils; @@ -111,7 +112,7 @@ public class AccountRecordProcessor extends DefaultStorageRecordProcessor(PREKEY_BATCH_SIZE); for (var i = 0; i < PREKEY_BATCH_SIZE; i++) { var preKeyId = (offset + i) % PREKEY_MAXIMUM_ID; - var keyPair = ECKeyPair.generate(); + var keyPair = Curve.generateKeyPair(); var record = new PreKeyRecord(preKeyId, keyPair); records.add(record); @@ -66,9 +66,13 @@ public class KeyUtils { final int signedPreKeyId, final ECPrivateKey privateKey ) { - var keyPair = ECKeyPair.generate(); + var keyPair = Curve.generateKeyPair(); byte[] signature; - signature = privateKey.calculateSignature(keyPair.getPublicKey().serialize()); + try { + signature = Curve.calculateSignature(privateKey, keyPair.getPublicKey().serialize()); + } catch (InvalidKeyException e) { + throw new AssertionError(e); + } return new SignedPreKeyRecord(signedPreKeyId, System.currentTimeMillis(), keyPair, signature); } diff --git a/lib/src/main/java/org/asamk/signal/manager/util/NumberVerificationUtils.java b/lib/src/main/java/org/asamk/signal/manager/util/NumberVerificationUtils.java index 659a8c67..921d7fc1 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/NumberVerificationUtils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/NumberVerificationUtils.java @@ -4,7 +4,6 @@ import org.asamk.signal.manager.api.CaptchaRequiredException; import org.asamk.signal.manager.api.IncorrectPinException; import org.asamk.signal.manager.api.NonNormalizedPhoneNumberException; import org.asamk.signal.manager.api.Pair; -import org.asamk.signal.manager.api.PinLockMissingException; import org.asamk.signal.manager.api.PinLockedException; import org.asamk.signal.manager.api.RateLimitException; import org.asamk.signal.manager.api.VerificationMethodNotAvailableException; @@ -115,7 +114,7 @@ public class NumberVerificationUtils { String pin, PinHelper pinHelper, Verifier verifier - ) throws IOException, PinLockedException, IncorrectPinException, PinLockMissingException { + ) throws IOException, PinLockedException, IncorrectPinException { verificationCode = verificationCode.replace("-", ""); try { final var response = verifier.verify(sessionId, verificationCode, null); @@ -128,7 +127,7 @@ public class NumberVerificationUtils { final var registrationLockData = pinHelper.getRegistrationLockData(pin, e); if (registrationLockData == null) { - throw new PinLockMissingException(); + throw e; } var registrationLock = registrationLockData.getMasterKey().deriveRegistrationLock(); diff --git a/lib/src/main/java/org/asamk/signal/manager/util/PhoneNumberFormatter.java b/lib/src/main/java/org/asamk/signal/manager/util/PhoneNumberFormatter.java deleted file mode 100644 index cc0c6503..00000000 --- a/lib/src/main/java/org/asamk/signal/manager/util/PhoneNumberFormatter.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.asamk.signal.manager.util; - -import com.google.i18n.phonenumbers.NumberParseException; -import com.google.i18n.phonenumbers.PhoneNumberUtil; -import com.google.i18n.phonenumbers.PhoneNumberUtil.PhoneNumberFormat; -import com.google.i18n.phonenumbers.Phonenumber.PhoneNumber; - -import org.asamk.signal.manager.api.InvalidNumberException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PhoneNumberFormatter { - - private static final Logger logger = LoggerFactory.getLogger(PhoneNumberFormatter.class); - - private static String impreciseFormatNumber(String number, String localNumber) { - number = number.replaceAll("[^0-9+]", ""); - - if (number.charAt(0) == '+') return number; - - if (localNumber.charAt(0) == '+') localNumber = localNumber.substring(1); - - if (localNumber.length() == number.length() || number.length() > localNumber.length()) return "+" + number; - - int difference = localNumber.length() - number.length(); - - return "+" + localNumber.substring(0, difference) + number; - } - - public static String formatNumber(String number, String localNumber) throws InvalidNumberException { - if (number == null) { - throw new InvalidNumberException("Null String passed as number."); - } - - if (number.contains("@")) { - throw new InvalidNumberException("Possible attempt to use email address."); - } - - number = number.replaceAll("[^0-9+]", ""); - - if (number.isEmpty()) { - throw new InvalidNumberException("No valid characters found."); - } - - try { - PhoneNumberUtil util = PhoneNumberUtil.getInstance(); - PhoneNumber localNumberObject = util.parse(localNumber, null); - - String localCountryCode = util.getRegionCodeForNumber(localNumberObject); - logger.trace("Got local CC: {}", localCountryCode); - - PhoneNumber numberObject = util.parse(number, localCountryCode); - return util.format(numberObject, PhoneNumberFormat.E164); - } catch (NumberParseException e) { - logger.debug("{}: {}", e.getClass().getSimpleName(), e.getMessage()); - return impreciseFormatNumber(number, localNumber); - } - } -} diff --git a/lib/src/main/java/org/asamk/signal/manager/util/Utils.java b/lib/src/main/java/org/asamk/signal/manager/util/Utils.java index daee1d77..b90a7873 100644 --- a/lib/src/main/java/org/asamk/signal/manager/util/Utils.java +++ b/lib/src/main/java/org/asamk/signal/manager/util/Utils.java @@ -7,7 +7,6 @@ import org.signal.libsignal.protocol.fingerprint.NumericFingerprintGenerator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.whispersystems.signalservice.api.NetworkResult; -import org.whispersystems.signalservice.api.NetworkResultUtil; import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.StreamDetails; @@ -155,7 +154,15 @@ public class Utils { } public static T handleResponseException(final NetworkResult response) throws IOException { - return NetworkResultUtil.toBasicLegacy(response); + final var throwableOptional = response.getCause(); + if (throwableOptional != null) { + if (throwableOptional instanceof IOException ioException) { + throw ioException; + } else { + throw new IOException(throwableOptional); + } + } + return response.successOrThrow(); } public static ByteString firstNonEmpty(ByteString... strings) { diff --git a/man/signal-cli.1.adoc b/man/signal-cli.1.adoc index 73286aac..32321095 100644 --- a/man/signal-cli.1.adoc +++ b/man/signal-cli.1.adoc @@ -316,11 +316,6 @@ Data URI encoded attachments must follow the RFC 2397. Additionally a file name can be added: e.g.: `data:;filename=;base64,` -*--view-once*:: -Send the message as a view once message. -A conformant client will only allow the receiver to view the message once. -View Once is only supported for messages that include an image attachment. - *--sticker* STICKER:: Send a sticker of a locally known sticker pack (syntax: stickerPackId:stickerId). Shouldn't be used together with `-m` as the official clients don't support this. diff --git a/run_tests.sh b/run_tests.sh index 339d9d7b..253532ec 100755 --- a/run_tests.sh +++ b/run_tests.sh @@ -141,7 +141,6 @@ exec 3> "$FIFO_FILE" echo '{"jsonrpc":"2.0","id":"id","method":"listGroups"}' >&3 echo '{"jsonrpc":"2.0","id":"id","method":"listDevices"}' >&3 echo '{"jsonrpc":"2.0","id":"id","method":"listIdentities"}' >&3 - echo '{"jsonrpc":"2.0","id":"id","method":"listStickerPacks"}' >&3 echo '{"jsonrpc":"2.0","id":"id","method":"sendSyncRequest"}' >&3 echo '{"jsonrpc":"2.0","id":"id","method":"sendContacts"}' >&3 echo '{"jsonrpc":"2.0","id":"id","method":"version"}' >&3 @@ -176,17 +175,6 @@ run_main -a "$NUMBER_2" receive run_main -a "$NUMBER_2" send "$NUMBER_1" -m hi run_main -a "$NUMBER_1" receive run_main -a "$NUMBER_2" receive -run_main -a "$NUMBER_1" updateAccount --discoverable-by-number=true -run_main -a "$NUMBER_2" removeContact --forget "$NUMBER_1" -run_main -a "$NUMBER_2" send "$NUMBER_1" -m hi -run_main -a "$NUMBER_2" send "$NUMBER_1" -m hii -run_main -a "$NUMBER_1" updateAccount --discoverable-by-number=false -run_main -a "$NUMBER_1" receive -run_main -a "$NUMBER_2" receive -run_main -a "$NUMBER_2" send "$NUMBER_1" -m hi -run_main -a "$NUMBER_2" send "$NUMBER_1" -m hii -run_main -a "$NUMBER_1" receive -run_main -a "$NUMBER_2" receive ## Groups GROUP_ID=$(run_main -a "$NUMBER_1" --output=json updateGroup -n GRUPPE -a LICENSE -m "$NUMBER_1" | jq -r '.groupId') run_main -a "$NUMBER_1" send "$NUMBER_2" -m first @@ -249,9 +237,7 @@ for OUTPUT in "plain-text" "json"; do run_linked -a "$NUMBER_1" --output="$OUTPUT" receive done -run_main -a "$NUMBER_1" --output="$OUTPUT" receive -run_main -a "$NUMBER_1" removeDevice -d 2 || true -run_main -a "$NUMBER_1" removeDevice -d 2 || true +run_main -a "$NUMBER_1" removeDevice -d 2 ## Unregister if [ "$TEST_REGISTER" -eq 1 ]; then diff --git a/src/main/java/org/asamk/signal/App.java b/src/main/java/org/asamk/signal/App.java index 6352aa13..e494d201 100644 --- a/src/main/java/org/asamk/signal/App.java +++ b/src/main/java/org/asamk/signal/App.java @@ -291,8 +291,6 @@ public class App { commandHandler.handleMultiLocalCommand(command, multiAccountManager); } catch (IOException e) { throw new IOErrorException("Failed to load local accounts file", e); - } catch (AccountCheckException e) { - throw new UnexpectedErrorException("Failed to load account file", e); } } diff --git a/src/main/java/org/asamk/signal/BaseConfig.java b/src/main/java/org/asamk/signal/BaseConfig.java index 730485bc..9218fe5f 100644 --- a/src/main/java/org/asamk/signal/BaseConfig.java +++ b/src/main/java/org/asamk/signal/BaseConfig.java @@ -8,7 +8,7 @@ public class BaseConfig { public static final String PROJECT_VERSION = BaseConfig.class.getPackage().getImplementationVersion(); static final String USER_AGENT_SIGNAL_ANDROID = Optional.ofNullable(System.getenv("SIGNAL_CLI_USER_AGENT")) - .orElse("Signal-Android/7.47.1"); + .orElse("Signal-Android/7.35.0"); static final String USER_AGENT_SIGNAL_CLI = PROJECT_NAME == null ? "signal-cli" : PROJECT_NAME + "/" + PROJECT_VERSION; diff --git a/src/main/java/org/asamk/signal/Shutdown.java b/src/main/java/org/asamk/signal/Shutdown.java index c51c12e4..a59497c9 100644 --- a/src/main/java/org/asamk/signal/Shutdown.java +++ b/src/main/java/org/asamk/signal/Shutdown.java @@ -1,6 +1,5 @@ package org.asamk.signal; -import org.asamk.signal.commands.exceptions.CommandException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -12,7 +11,7 @@ import sun.misc.Signal; public class Shutdown { private static final Logger logger = LoggerFactory.getLogger(Shutdown.class); - private static final CompletableFuture shutdown = new CompletableFuture<>(); + private static final CompletableFuture shutdown = new CompletableFuture<>(); private static final CompletableFuture shutdownComplete = new CompletableFuture<>(); private static boolean initialized = false; @@ -44,17 +43,9 @@ public class Shutdown { shutdown.complete(null); } - public static void triggerShutdown(CommandException exception) { - logger.debug("Triggering shutdown with exception.", exception); - shutdown.complete(exception); - } - - public static void waitForShutdown() throws InterruptedException, CommandException { + public static void waitForShutdown() throws InterruptedException { try { - final var result = shutdown.get(); - if (result instanceof CommandException e) { - throw e; - } + shutdown.get(); } catch (ExecutionException e) { throw new RuntimeException(e); } diff --git a/src/main/java/org/asamk/signal/commands/DaemonCommand.java b/src/main/java/org/asamk/signal/commands/DaemonCommand.java index 6790c65d..197e1286 100644 --- a/src/main/java/org/asamk/signal/commands/DaemonCommand.java +++ b/src/main/java/org/asamk/signal/commands/DaemonCommand.java @@ -97,7 +97,7 @@ public class DaemonCommand implements MultiLocalCommand, LocalCommand { final OutputWriter outputWriter ) throws CommandException { Shutdown.installHandler(); - logger.info("Starting daemon in single-account mode for {}", m.getSelfNumber()); + logger.info("Starting daemon in single-account mode for " + m.getSelfNumber()); final var noReceiveStdOut = Boolean.TRUE.equals(ns.getBoolean("no-receive-stdout")); final var receiveMode = ns.get("receive-mode"); final var receiveConfig = getReceiveConfig(ns); diff --git a/src/main/java/org/asamk/signal/commands/FinishChangeNumberCommand.java b/src/main/java/org/asamk/signal/commands/FinishChangeNumberCommand.java index 1242c194..8fce4dbf 100644 --- a/src/main/java/org/asamk/signal/commands/FinishChangeNumberCommand.java +++ b/src/main/java/org/asamk/signal/commands/FinishChangeNumberCommand.java @@ -9,7 +9,6 @@ import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.api.IncorrectPinException; import org.asamk.signal.manager.api.NotPrimaryDeviceException; -import org.asamk.signal.manager.api.PinLockMissingException; import org.asamk.signal.manager.api.PinLockedException; import org.asamk.signal.output.OutputWriter; @@ -51,8 +50,6 @@ public class FinishChangeNumberCommand implements JsonRpcLocalCommand { + "\nUse '--pin PIN_CODE' to specify the registration lock PIN"); } catch (IncorrectPinException e) { throw new UserErrorException("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining()); - } catch (PinLockMissingException e) { - throw new UserErrorException("Account is pin locked, but pin data has been deleted on the server."); } catch (NotPrimaryDeviceException e) { throw new UserErrorException("This command doesn't work on linked devices."); } catch (IOException e) { diff --git a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java index eab4155c..e3d36d85 100644 --- a/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java +++ b/src/main/java/org/asamk/signal/commands/GetUserStatusCommand.java @@ -64,16 +64,9 @@ public class GetUserStatusCommand implements JsonRpcLocalCommand { } final var usernames = ns.getList("username"); - final Map registeredUsernames; - try { - registeredUsernames = usernames == null ? Map.of() : m.getUsernameStatus(new HashSet<>(usernames)); - } catch (IOException e) { - throw new IOErrorException("Unable to check if users are registered: " - + e.getMessage() - + " (" - + e.getClass().getSimpleName() - + ")", e); - } + final var registeredUsernames = usernames == null + ? Map.of() + : m.getUsernameStatus(new HashSet<>(usernames)); // Output switch (outputWriter) { diff --git a/src/main/java/org/asamk/signal/commands/SendCommand.java b/src/main/java/org/asamk/signal/commands/SendCommand.java index 98051b23..39be74ee 100644 --- a/src/main/java/org/asamk/signal/commands/SendCommand.java +++ b/src/main/java/org/asamk/signal/commands/SendCommand.java @@ -66,9 +66,6 @@ public class SendCommand implements JsonRpcLocalCommand { .help("Add an attachment. " + "Can be either a file path or a data URI. Data URI encoded attachments must follow the RFC 2397. Additionally a file name can be added, e.g. " + "data:;filename=;base64,."); - subparser.addArgument("--view-once") - .action(Arguments.storeTrue()) - .help("Send the message as a view once message"); subparser.addArgument("-e", "--end-session", "--endsession") .help("Clear session state and send end session message.") .action(Arguments.storeTrue()); @@ -167,7 +164,6 @@ public class SendCommand implements JsonRpcLocalCommand { if (attachments == null) { attachments = List.of(); } - final var viewOnce = Boolean.TRUE.equals(ns.getBoolean("view-once")); final var selfNumber = m.getSelfNumber(); @@ -243,7 +239,6 @@ public class SendCommand implements JsonRpcLocalCommand { try { final var message = new Message(messageText, attachments, - viewOnce, mentions, Optional.ofNullable(quote), Optional.ofNullable(sticker), @@ -255,14 +250,8 @@ public class SendCommand implements JsonRpcLocalCommand { : m.sendMessage(message, recipientIdentifiers, notifySelf); outputResult(outputWriter, results); } catch (AttachmentInvalidException | IOException e) { - if (e instanceof IOException io && io.getMessage().contains("No prekeys available")) { - throw new UnexpectedErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass() - .getSimpleName() + "), maybe one of the devices of the recipient wasn't online for a while.", - e); - } else { - throw new UnexpectedErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass() - .getSimpleName() + ")", e); - } + throw new UnexpectedErrorException("Failed to send message: " + e.getMessage() + " (" + e.getClass() + .getSimpleName() + ")", e); } catch (GroupNotFoundException | NotAGroupMemberException | GroupSendingNotAllowedException e) { throw new UserErrorException(e.getMessage()); } catch (UnregisteredRecipientException e) { diff --git a/src/main/java/org/asamk/signal/commands/VerifyCommand.java b/src/main/java/org/asamk/signal/commands/VerifyCommand.java index 6a5046bc..a8543c5a 100644 --- a/src/main/java/org/asamk/signal/commands/VerifyCommand.java +++ b/src/main/java/org/asamk/signal/commands/VerifyCommand.java @@ -11,7 +11,6 @@ import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.RegistrationManager; import org.asamk.signal.manager.api.IncorrectPinException; -import org.asamk.signal.manager.api.PinLockMissingException; import org.asamk.signal.manager.api.PinLockedException; import org.asamk.signal.output.JsonWriter; import org.slf4j.Logger; @@ -77,8 +76,6 @@ public class VerifyCommand implements RegistrationCommand, JsonRpcRegistrationCo + "\nUse '--pin PIN_CODE' to specify the registration lock PIN"); } catch (IncorrectPinException e) { throw new UserErrorException("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining()); - } catch (PinLockMissingException e) { - throw new UserErrorException("Account is pin locked, but pin data has been deleted on the server."); } catch (IOException e) { throw new IOErrorException("Verify error: " + e.getMessage(), e); } diff --git a/src/main/java/org/asamk/signal/dbus/DbusHandler.java b/src/main/java/org/asamk/signal/dbus/DbusHandler.java index 2ed6d11f..b6799de7 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusHandler.java +++ b/src/main/java/org/asamk/signal/dbus/DbusHandler.java @@ -1,21 +1,17 @@ package org.asamk.signal.dbus; import org.asamk.signal.DbusConfig; -import org.asamk.signal.Shutdown; import org.asamk.signal.commands.exceptions.CommandException; -import org.asamk.signal.commands.exceptions.IOErrorException; import org.asamk.signal.commands.exceptions.UnexpectedErrorException; import org.asamk.signal.commands.exceptions.UserErrorException; import org.asamk.signal.manager.Manager; import org.asamk.signal.manager.MultiAccountManager; -import org.freedesktop.dbus.connections.IDisconnectCallback; import org.freedesktop.dbus.connections.impl.DBusConnection; import org.freedesktop.dbus.connections.impl.DBusConnectionBuilder; import org.freedesktop.dbus.exceptions.DBusException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -98,9 +94,7 @@ public class DbusHandler implements AutoCloseable { final var busType = isDbusSystem ? DBusConnection.DBusBusType.SYSTEM : DBusConnection.DBusBusType.SESSION; logger.debug("Starting DBus server on {} bus: {}", busType, busname); try { - dBusConnection = DBusConnectionBuilder.forType(busType) - .withDisconnectCallback(new DisconnectCallback()) - .build(); + dBusConnection = DBusConnectionBuilder.forType(busType).build(); dbusRunner.run(dBusConnection); } catch (DBusException e) { throw new UnexpectedErrorException("Dbus command failed: " + e.getMessage(), e); @@ -147,13 +141,4 @@ public class DbusHandler implements AutoCloseable { void run(DBusConnection connection) throws DBusException; } - - private static final class DisconnectCallback implements IDisconnectCallback { - - @Override - public void disconnectOnError(IOException ex) { - logger.debug("DBus daemon disconnected unexpectedly, shutting down"); - Shutdown.triggerShutdown(new IOErrorException("Unexpected dbus daemon disconnect", ex)); - } - } } diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java index 50150a98..cf6999a9 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalControlImpl.java @@ -10,7 +10,6 @@ import org.asamk.signal.manager.RegistrationManager; import org.asamk.signal.manager.api.CaptchaRequiredException; import org.asamk.signal.manager.api.IncorrectPinException; import org.asamk.signal.manager.api.NonNormalizedPhoneNumberException; -import org.asamk.signal.manager.api.PinLockMissingException; import org.asamk.signal.manager.api.PinLockedException; import org.asamk.signal.manager.api.RateLimitException; import org.asamk.signal.manager.api.UserAlreadyExistsException; @@ -106,8 +105,6 @@ public class DbusSignalControlImpl implements org.asamk.SignalControl { + (e.getTimeRemaining() / 1000 / 60 / 60)); } catch (IncorrectPinException e) { throw new Error.Failure("Verification failed! Invalid pin, tries remaining: " + e.getTriesRemaining()); - } catch (PinLockMissingException e) { - throw new Error.Failure("Account is pin locked, but pin data has been deleted on the server."); } } diff --git a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java index 725df8b1..ac77df99 100644 --- a/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java +++ b/src/main/java/org/asamk/signal/dbus/DbusSignalImpl.java @@ -236,7 +236,6 @@ public class DbusSignalImpl implements Signal, AutoCloseable { try { final var message = new Message(messageText, attachments, - false, List.of(), Optional.empty(), Optional.empty(), @@ -400,7 +399,6 @@ public class DbusSignalImpl implements Signal, AutoCloseable { try { final var message = new Message(messageText, attachments, - false, List.of(), Optional.empty(), Optional.empty(), @@ -446,7 +444,6 @@ public class DbusSignalImpl implements Signal, AutoCloseable { try { final var message = new Message(messageText, attachments, - false, List.of(), Optional.empty(), Optional.empty(),