Closed tiesselune closed 2 years ago
What? Somebody else wrote an ece crate? Oh nice! The amount of tears and pain to write it with ring
and to understand the RFCs are now gone. This is sweet, waiting for the finished version :D
Please poke me if you're done and I'm not answering soon enough. A new sprint starting and I'm in the middle of the long meetings. Also, please update the README and see that the rustdocs reflect the current state of the crate.
For breaking changes, we go to v0.8 anyhow because of Tokio 1 and (if somebody does it) a possible support for async-std runtime. So if you need to break any apis, now's the time.
Great news, my ece
crate pull request has been approved and merged, and the new version published to crates.io which means that this pull request is soon to get out of WIP state! 🥳
Ok @pimeys , responding here cause the two concerns you presented above are actually linked. I first responded with some suggestions on how to fix the problem then dove into it and found a far simpler approach that is just a bit suboptimal in regard to code duplication between the ece
crate and this one, but would be better performance-wise. So I deleted my previous answers since they're no longer relevant and don't deserve to be read. 😉
The headers
function from the AesGcmEncryptedBlock
struct that we get from the encrypt_aesgcm
function is the culprit here; it's passing self
by value, effectively consuming the block and forcing a copy to avoid a double move; it's also producing the suboptimal hashmap. The good thing is: we don't need it. So we can get rid of the cloning and the hashmap in one go by re-introducing a variant of get_headers
function that you originally wrote for this even if the ece
crates has a function that essentially does the same thing (but with Strings and consuming Self, forcing a copy somewhere) That's definitely a design flaw that would be fixed in another pull request for the ece
crate 😉, but we can circumvent it for now quite easily.
Anyway, I'm going to submit a new commit for both those issues quite soon ;)
EDIT: For reference, I've just suggested these changes to the ece
crate maintainers, and might tackle it if they want me to
Great. Probably this kind of optimization doesn't matter for most users, but before we went bankrupt with the company I was writing this crate for, we used it to send thousands and thousands notifications per second. All extra allocations start to show up, and, well, it's very cool if you can make it as fast as possible. :D
I can accept this of course as-is too, if there's no way around some of the added computation.
Hello @pimeys Just to let you know that I wrote a version that avoids the allocation/hashing, but in order to fix this properly, I've opened a new pull request on the ece
crate for that new issue.
There would not be any performance difference, just a question of using the functions provided by the ece
crate instead of re-coding them, but basically the code is the same.
Anyway, there would be no breaking change and moving from that implementation to the one in the ece
crate would be very easy and could be done at any time.
(I still need to run some real-world tests before merging)
Hi again @pimeys ! So I have good news and bad news.
Good news: I tested the Aes128Gcm back-end with real world notifications and it works!
Bad news: for it to work, I had to downgrade hyper
, hyper-tls
and tokio
. If I run it with the current versions, I got the following error: there is no reactor running, must be called from the context of a Tokio 1.x runtime
in the hyper::Client::send
method that is called in WebPushClient::send
. With the old versions, I got random stack overflows, still somewhere in the WebPushClient::send
request.
Would you be familiar with the Tokio problem? Does the problem occur on your end with the current master
branch ?
I'm trying to debug this on your branch, but I don't really have proper subscription info or anything, so I go with the following:
{
"endpoint": "asdf",
"keys": {
"p256dh": "asdf",
"auth": "asdf"
}
}
I get:
Finished dev [unoptimized + debuginfo] target(s) in 0.05s
Running `target/debug/examples/simple_send -f info.json`
Error: Unspecified
which means that the Tokio 1.1 and Hyper 0.14 work just as they should. The error you get is that you try to run something that expects Tokio 1 in a Tokio 0.2 or 0.3 reactor. That's unfortunate how Tokio forces you to use their machinery and exact versions. Have you tried cargo clean
and really be sure you run the push system at least with Tokio version 1.0 or later?
Hey, thanks for the quick reply. I was investigating and I came to the same conclusion. My example uses actix and it seems that the current actix_web version has a dependency that itself uses tokio 0.2. I'll need to try it with the beta version of actix.
This is the reason I'd like this crate, a2 and fcm all to be independent on runtimes. Maybe refactoring it using https://docs.rs/async-h1/2.3.1/async_h1/ would already make it work much better with every possible system...
Btw. I started hacking away trying to make this crate runtime-independent. This is not really in scope of this ticket, but I'm in Matrix: @oh_lawd:nauk.io if you want to chat more about the general direction of rust-web-push :)
I've tested against
And I am proud to announce that it works! I think this is ready for merging or at least a review ;)
@tiesselune is it now ok to merge? I'm probably not releasing a new version until we get the runtime PR merged too. Then we go one major version up.
I'd like to make one more commit, but since we're going to merge your other PR and those two have a bunch of smallish formatting conflicts, it's maybe better to update it first once your other PR is merged (I did it once to test the infamous stack-overflow hyper
/actix
problem so the branch is basically ready, but it's on another local branch on my computer).
Re-converting to draft, just noticed I had some weird test failures I still have to investigate.
Update: the test failures come from the fact that padding has changed between the previously implemented version and the ece
crate version.
Pondering if we should re-introduce padding on both schemes
About
This pull request addresses #3 by using the
ece
crate, which is maintained by Mozilla, to implement the Aes128Gcm encoding scheme. This way, it can be easily updated and benefit from security reviews and patches on theece
crate and the crate can focus on the VAPID part of things.For consistency purposes, it entirely delegates ECE encoding to the
ece
crate, including the AesGcm scheme, which implies some refactoring.The actual cryptographic work being implemented and tested in the
ece
crate, the cryptographic functions and tests in thehttp_ece
module can be entirely delegated.Changes summary:
encrypt
function in theHttpEce
struct implementation to support both encodings and use theece
crate, using the same interface to avoid any breaking changeheaders
property of theWebPushPayload
struct from aVec<(&'static str,String)>
to aHashMap<String,String>
for ease of integration and consistency with theece
crate implementation (this might be a breaking change, sinceWebPushPayload
is published at the crate level; it needs more investigation)http-ece
from the tags of the crate, since it is now delegated to another one.Remaining work
This pull request is a draft and it needs a few things before it can be considered:
ece
crate, which I'm working on with the maintainer ( for now,cargo.toml
uses my fork)WebPushPayload
struct needs to be addressedece
crate would allow integrating with its headers function without extra allocation or hashing