This simplifies SignalProtocolError at the cost of an extra heap
allocation for other errors. On its own, that probably isn't worth it,
but this lays groundwork for propagating exceptions / errors back up
in the native environment.
There were two discrepancies between the logic here and the original
logic of libsignal-protocol-java.
First, if the session record had an uninitialized active session, in
Java this would still attempt decryption with the old session states,
but Rust would stop immediately without trying the old states. [I am
not sure if this ever happens but it could possibly occur due to use
of archiveCurrentState]
Secondly, we returned the wrong error condition. We treated lack of a
sender chain as an invalid state (effectively an internal error) but
Java treats it as an invalid message, which makes sense in so far as
it is a message which we are unable to process with the information we
have available. This wrong error type led to an unexpected exception
being thrown in Android.
In libsignal-protocol-java, SessionRecord holds a SesssionState struct which is
the "active" session plus a list of old states. If the record is freshly
created, there is still a SessionState, but it is an uninitialized/new protobuf
structure which causes all fields to be empty/zero/false.
So in the original Java logic you can call for example hasSenderChain, and on
an empty/fresh record it will return false. However in Rust, in this case the
Option is empty and we return an error instead.
For hasSenderChain, it seems reasonable to return false if there is no active
session, since if there is no session there is certainly no chain.
Android also expects the session version to be == 0 on such sessions, but this
makes less sense, so have this logic only in the Java binding and not in the
Rust library proper.
- Verify its correctness with build_ffi.sh --verify-ffi
- Regenerate with build_ffi.sh --generate-ffi
This simplifies the header search logic for both SwiftPM and
CocoaPods, as well as saving on build time by avoiding cbindgen.
The tweak to cbindgen.toml to prefer typedef-based structs and enums
is sidestepping an incompatibility between cbindgen 0.15.0 (which
GitHub has installed) and 0.16.0 (which allows reusing a release build
directory as well as a debug one).
Rust build scripts and proc-macros are compiled for the host, rather
than the target, which means they need a search path to link against
the host's libraries. macOS Big Sur doesn't provide that in the
default search paths anymore, so we add one manually based on an
environment variable provided by Xcode.
When building a cdylib, Rust currently doesn't export public symbols
on Linux if they come from a dependency. However, enabling LTO gets
around this by performing the filtering step after the merging.
https://github.com/rust-lang/rfcs/issues/2771
This is useful for our Rust CI, which runs things like
`cargo test --all` by default. Cargo features are considered
additive, so in order to build libsignal-ffi and libsignal-jni, a
hybrid libsignal-bridge ends up getting built (instead of two copies)