aboutsummaryrefslogtreecommitdiffstats
path: root/src/daemon.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon.rs')
-rw-r--r--src/daemon.rs155
1 files changed, 152 insertions, 3 deletions
diff --git a/src/daemon.rs b/src/daemon.rs
index 4895a48..8952d78 100644
--- a/src/daemon.rs
+++ b/src/daemon.rs
@@ -36,6 +36,143 @@ const REJOIN_INTERVAL: Duration = Duration::from_secs(60);
/// How often to sync DHT-replicated values to local store (5 s).
const SYNC_INTERVAL: Duration = Duration::from_secs(5);
+const INDEX_PAGE: &str = "\
+tesseras-paste
+
+ Decentralized pastebin built on the tesseras-dht
+ Kademlia DHT. Pastes are encrypted with XChaCha20-
+ Poly1305, content-addressed via SHA-256, and
+ replicated across the network. No accounts, no
+ databases, no JavaScript.
+
+ \"In the beginning there was the server,
+ and the server was centralized,
+ and the centralized was fragile,
+ and the fragile was doomed.\"
+
+ -- Apocrypha of the Lost Nodes
+
+
+Why
+
+ Pastebin.com sold out and filled with ads.
+ Ghostbin shut down. Hastebin went offline.
+ ZeroBin stopped being maintained.
+ PrivateBin requires a server you must trust.
+
+ Every centralized pastebin is one decision away
+ from disappearing, censoring, or monetizing your
+ content.
+
+ We got tired of renting someone else's clipboard.
+
+ tesseras-paste has no single point of failure.
+ No company can shut it down. No server can be
+ seized. Your paste lives as long as the network
+ has nodes.
+
+
+Philosophy
+
+ We believe in:
+ - Code you can read in an afternoon
+ - Protocols you can implement in a weekend
+ - Systems that work without permission
+ - Networks that survive their creators
+
+ We do not believe in:
+ - Move fast and break things
+ - Microservices for a text file
+ - 400MB Docker images to serve hello world
+ - npm install the-entire-internet
+
+
+How it works
+
+ 1. You write text (or pipe it from stdin)
+ 2. tp encrypts it with a random key
+ 3. SHA-256 hashes the ciphertext into a content
+ address
+ 4. The encrypted blob is stored on the K-closest
+ DHT nodes
+ 5. The URL contains the only key that decrypts it
+ 6. The network never sees your plaintext
+
+
+Quick start
+
+ Install from crates.io:
+
+ $ cargo install tesseras-paste
+
+ Start the daemon (connects to the public bootstrap
+ nodes automatically via DNS SRV):
+
+ $ tpd -d /var/tesseras-paste -w 9999
+
+ Create a paste:
+
+ $ echo 'hello world' | tp put
+ 4zxDwJQEte37CQE4xzVCB1GaNodBprLUHjHcWzhTqP7Y#...
+
+ Retrieve it:
+
+ $ tp get 4zxDwJQEte37CQE4xzVCB1GaNodBprLUHjHcWzhTqP7Y#...
+ hello world
+
+ Public (unencrypted) paste:
+
+ $ echo 'visible to all' | tp put -p
+ EbpnKntDRBkuDKJuFKY7Ke7jM9ygtLCSYpmykXvzWb8U
+
+ Pin a paste so it never expires:
+
+ $ tp pin <key>
+
+
+Bootstrap nodes
+
+ bootstrap1.tesseras.net port 4433
+ bootstrap2.tesseras.net port 4433
+
+
+Source code
+
+ official https://got.tesseras.net
+ mirror https://git.tesseras.net
+ sourcehut https://git.sr.ht/~ijanc/tesseras
+ github https://github.com/tesseras-net
+
+
+Donate
+
+ Bitcoin bc1qm3srpwnpe3y58mhn7lp37lyw0s45tfdganvat5
+
+
+Website
+
+ https://tesseras.net
+
+
+Greets
+
+ To my beloved Aninha, for the patience and love.
+
+ To the cypherpunks, for writing code instead
+ of laws.
+
+ To OpenBSD, for building an OS where security
+ is not a feature but a principle.
+
+ To everyone running a node: you ARE the network.
+
+
+See also
+
+ tp(1) https://p.tesseras.net/64RQsdrPsmtdYzLQX9SQN3NBkuU1fD1pQMGdYkUXERV5
+ tpd(1) https://p.tesseras.net/Ho4jVs1tj4endcZ3ymus3Tm33XGze2tz2K8Qey4EMTRD
+";
+
/// A request from the socket thread to the main thread.
pub struct DaemonRequest {
pub cmd: Request,
@@ -56,6 +193,15 @@ pub fn run_daemon(
let mut last_sync = Instant::now();
let mut last_rejoin = Instant::now();
+ // Block + remove paste on disk when a remote
+ // delete (store TTL=0) arrives from the DHT.
+ let del_store = store.clone();
+ node.set_delete_callback(move |key: &[u8]| {
+ del_store.block(key);
+ del_store.remove_paste(key);
+ log::info!("remote delete: blocked key {}", crate::base58::encode(key));
+ });
+
log::info!("daemon main loop started");
while !shutdown.load(Ordering::Relaxed) {
@@ -189,8 +335,8 @@ fn handle_request(
store.paste_count(),
m.messages_sent,
m.messages_received,
- m.lookups_completed,
m.lookups_started,
+ m.lookups_completed,
);
Response::Ok(status)
}
@@ -205,6 +351,9 @@ fn sync_dht_to_store(node: &Node, store: &PasteStore) {
if key.len() != 32 {
continue;
}
+ if store.is_blocked(&key) {
+ continue;
+ }
if store.get_paste(&key).is_none() {
let _ = store.put_paste(&key, &value);
}
@@ -473,8 +622,8 @@ fn handle_http(
http_response(
&mut stream,
200,
- "text/plain",
- b"Hello Tesseras World\n",
+ "text/plain; charset=utf-8",
+ INDEX_PAGE.as_bytes(),
);
return;
}