Ffsend – Share Files from the CLI: A Firefox Send Client Written in Rust
gitlab.com
gitlab.com
I dove in to see how they solve the routing / firewall problem. Turns out you’re relying on the kindness of strangers and a public WebSocket relay. Hard to see how they could do any better, alas.
IMO one of the big holes in the architecture of the web is the lack of a standard peer-to-peer “content-addressable routing” protocol, perhaps based on any of a number of distributed hash table schemes. It’d be perfect for something like this.
Unfortunately, the academic work on DHTs emerged at around the same time as both the stultifying dominance of Internet Explorer and the panic over Napster et al.
Sending files: `croc [files]` Receiving files: `croc code-phrase`
Custom code-phrases are supported.
More information on design decisions are documented in a blog post [1].
For some definition of "better", sure. I really do wonder why the author didn't make it compatible with magic-wormhole. Seems a bit silly to cause incompatibility between two implementations that are so similar that they are functionally identical.
> Custom code-phrases are supported.
magic-wormhole supports that too (you still need to have a channel number but you can pick that too).
The one feature of croc which magic-wormhole doesn't have is transfer resumption (though I do wonder how difficult it would've been to add this to magic-wormhole -- or to at least extend the magic-wormhole API to support it). As far as I can tell, the only other real benefit of croc is "it's written in Go" -- which is a real benefit for some people (most notably, Windows users without a working Python setup) but it's not really one that justifies having an incompatible version of basically the same idea.
This is not to discourage others from building on top of wormhole-william. I built the public API[1] first and then added the CLI tool with the hope that others would be able to easily pick it up and use it in other applications.
[1]: https://pkg.go.dev/github.com/psanford/wormhole-william/worm...
Edit: It seems equally slow to me when using the website, so I suspect the issue is with Mozilla's sever, not the client.
CPU: Intel(R) Core(TM) i7-8565U CPU @ 1.80GHz
Kernel: Linux 4.19.0-6-amd64
Distro: Debian 10.2
Rust: rustc 1.40.0 (73528e339 2019-12-16)
Program: ffsend 0.2.57
Probably I could combine Fsend and another CLI tool to enable that use case. Right now I'm manually typing links into different devices.
EDIT: Fsend can do this by itself!
Obligatory web alternatives that are peer to peer -
[1]: https://github.com/kern/file.pizza
[2]: https://github.com/cowbell/sharedrop
[3]: https://github.com/webtorrent/instant.io
https://web.archive.org/web/20190401042439/http://blog.mbrt....
Here's what the main function looks like:
fn main() {
match Args::parse().and_then(run) {
Ok(count) if count == 0 => process::exit(1),
Ok(_) => process::exit(0),
Err(err) => {
eprintln!("{}", err);
process::exit(1);
}
}
}If your code is stateful the typestate pattern is particularly easy to write in Rust - http://cliffle.com/blog/rust-typestate/
Only if you are not behind symmetric NAT I suppose.
Tangent: why does symmetric NAT exist? It seems like the kind of thing firewall fetishists do "for security" without considering the problems it causes and without any clue of what sort of attack it thwarts that mere stateful firewalling does not thwart.
Realize that without symmetric NAT, TURN would be largely unnecessary.
This works with most if not all netcat implementations.
> The basic file transmission technique described at the beginning of this section fails if neither participating host is capable of listening, or the two hosts can't communicate directly. This situation has become common with the prevalence of network address translation. A way to work around it is to use a third host as an intermediary. The intermediate host listens in connection brokering mode and the other two hosts connect to it. Recall from the section called “Connection Brokering” that in connection brokering mode any input received on one socket is copied and sent out to all other sockets. With just two hosts connected this is especially simple: anything coming from one host gets forwarded to the other. This example shows host1 sending inputfile to outputfile on host2, using host3 as an intermediary.[1]
This works nicely with Nmap's Ncat.
Sender:
curl https://patchbay.pub/random-channel-chosen-by-you --data-binary @file.mp4
Receiver:
curl https://patchbay.pub/random-channel-chosen-by-you
As mentioned by others, https://file.pizza is great if both devices have browsers, and the WebRTC connection between them succeeds.
Would be great to have something like curl -X POST @myFilePath "https://api.send.firefox.com"
EDIT: Ah, they mention magic-wormhole in the acknowledgements as being an inspiration.
Except mobile; it would be quite awesome if that were to exist as well.
woof -i <ip_address> -p <port> <filename>
termux: https://play.google.com/store/apps/details?id=com.termux
woof: http://www.home.unix-ag.org/simon/woof.html
1. Allows directory upload/download (tar/gzip/bzip2 compressed)
2. Local file server (doesn't need to go over the internet)
3. Allows upload form (-U option)
4. Allows file to be served <count> number of times (-c option)
Edit: I see now. Thanks
For managing project dependencies, Poetry is the current best. It means I dont have to interact with virtualenv or pip or setuptools or pip-tools or manifest.in.
I don't do a lot of Go either but at least Go generates freestanding binaries so if I install it in precompiled form I know that it will be fairly frictionless and won't rely on half a billion dependencies (which may or may not conflict with something else). I use a bunch of Go programs regularly (like docker or Arch's yay package manager) and it never gets on in the way.
On the other hand if it's an npm package I don't even think about it.
- single binary deploy(unlike Python)
- fast (llvm)
- memory efficient (no GC)
- newer (by virtue of the newness of the language itself).
Nothing wrong with setting expectations in title ;-)
Aha. I have a web server written in rust that literally uses about 5Mb memory on RPi. And that one actually has a proper web framework, not something barebones.
Good luck doing that in Python.
I'm looking at REST API frameworks for rust these days, but nothing looks decent...
python3 -m http.server
Note also that Python is primarily reference counted, with GC used only to detect cyclic references.On top of this, you can do the same with docker run nginx -v.:/var/www (which btw is a similar number of symbols). Also python’s http module barely supports anything but the most basic content-types (so good luck with eg SVGs).
Tradeoffs everywhere, which make sense or not depending on your requirements.
But Python's ref counting isn't a significant factor in its memory use.
Are you implying nginx uses more memory than a python interpreter? :)
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 23612 1.2 1.7 62412 17492 pts/1 S+ 12:38 0:00 | \_ python3 -m http.serverOn top of that, that server doesn't actually use any sorts of downgraded language version that Java EE is.
You literally get that for free with Rust.
I still don't understand why people argue against this. Rust is a better language in so many aspects (tooling, language capabilities) it's really hard to argue against it.
No GC forces the programmer to think about memory, this is a good thing because you need to to that in all garbabe collected languages anyway - or you will get bloat.
For most use cases I consider garbage collection to be a mistake. Scripting languages or small one-off applications exempted.
Besides that, Mozilla and the Firefox community have a lot of Rust devs so writing this in Rust may make this more likely to get PRs from people involved in the FF Send project
sum=$(sha1sum "$1" | cut -f 1 -d ' ')
ssh your-vps mkdir /srv/http/files/$sum
scp "$1" your-vps:/srv/http/files/$sum/
echo https://your-vps/files/$sum/$1
+ nginx or whateverI can and do own that HW. At least as much as one can own anything - it's located in my appartment. You can just as well run the web server from your own workstation/laptop.
The only reason to put shared files on other computer is that the other computer is more available.
Also it can't be a "secure sharing service" if you're still using 'sha1sum' and it not being end-to-end encrypted...
Also it's quite secure since file content is clearly mapped to the URL you're sharing with the other party via independent channel and the receiving party can verify the content of the file.
It may not be completely private if VPS does not run on your own HW, but nothing prevents you from running it on your own HW in your secured location.
You can use this on windows the same way you'd use it on Linux. You just install a bunch of programs and run commands from command line. (basically just like you'd need to do with fsend) It's less hassle on Linux, since the commands are pre-installed. Fsend is more hassle on Linux since it's not preinstalled and requires rust, compilation, etc.
The other people just open a https links and download files in any browser or via curl, no tools required at all, not even JS.
python 2.7 >python -m SimpleHTTPServer 8080
python 3 > python -m http.server 8080
Python’s built-in HTTP server is pretty useful. It doesn’t really overlap with the functionality of use-cases of a Send client much at all.