mirror of
https://github.com/romanz/electrs.git
synced 2024-11-19 01:43:29 +01:00
Abstract cookie handling to a trait object
This would allow re-loading JSONRPC cookie after bitcoind restart
This commit is contained in:
parent
91e4dd8b6f
commit
1d59449677
@ -19,7 +19,7 @@ fn run() -> Result<()> {
|
||||
let daemon = Daemon::new(
|
||||
&config.daemon_dir,
|
||||
config.daemon_rpc_addr,
|
||||
&config.cookie,
|
||||
config.cookie_getter(),
|
||||
config.network_type,
|
||||
&metrics,
|
||||
)?;
|
||||
|
@ -21,7 +21,7 @@ fn run(config: Config) -> Result<()> {
|
||||
let daemon = Daemon::new(
|
||||
&config.daemon_dir,
|
||||
config.daemon_rpc_addr,
|
||||
&config.cookie,
|
||||
config.cookie_getter(),
|
||||
config.network_type,
|
||||
&metrics,
|
||||
)?;
|
||||
|
@ -20,7 +20,7 @@ fn run_server(config: &Config) -> Result<()> {
|
||||
let daemon = Daemon::new(
|
||||
&config.daemon_dir,
|
||||
config.daemon_rpc_addr,
|
||||
&config.cookie,
|
||||
config.cookie_getter(),
|
||||
config.network_type,
|
||||
&metrics,
|
||||
)?;
|
||||
|
@ -3,21 +3,13 @@ use std::env::home_dir;
|
||||
use std::fs;
|
||||
use std::net::SocketAddr;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use stderrlog;
|
||||
|
||||
use daemon::Network;
|
||||
use daemon::{CookieGetter, Network};
|
||||
|
||||
use errors::*;
|
||||
|
||||
fn read_cookie(daemon_dir: &Path) -> Result<String> {
|
||||
let mut path = daemon_dir.to_path_buf();
|
||||
path.push(".cookie");
|
||||
let contents = String::from_utf8(
|
||||
fs::read(&path).chain_err(|| format!("failed to read cookie from {:?}", path))?
|
||||
).chain_err(|| "invalid cookie string")?;
|
||||
Ok(contents.trim().to_owned())
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Config {
|
||||
pub log: stderrlog::StdErrLog,
|
||||
@ -25,7 +17,7 @@ pub struct Config {
|
||||
pub db_path: PathBuf, // RocksDB directory path
|
||||
pub daemon_dir: PathBuf, // Bitcoind data directory
|
||||
pub daemon_rpc_addr: SocketAddr, // for connecting Bitcoind JSONRPC
|
||||
pub cookie: String, // for bitcoind JSONRPC authentication ("USER:PASSWORD")
|
||||
pub cookie: Option<String>, // for bitcoind JSONRPC authentication ("USER:PASSWORD")
|
||||
pub electrum_rpc_addr: SocketAddr, // for serving Electrum clients
|
||||
pub monitoring_addr: SocketAddr, // for Prometheus monitoring
|
||||
pub skip_bulk_import: bool, // slower initial indexing, for low-memory systems
|
||||
@ -141,9 +133,7 @@ impl Config {
|
||||
Network::Testnet => daemon_dir.push("testnet3"),
|
||||
Network::Regtest => daemon_dir.push("regtest"),
|
||||
}
|
||||
let cookie = m.value_of("cookie")
|
||||
.map(|s| s.to_owned())
|
||||
.unwrap_or_else(|| read_cookie(&daemon_dir).unwrap());
|
||||
let cookie = m.value_of("cookie").map(|s| s.to_owned());
|
||||
|
||||
let mut log = stderrlog::new();
|
||||
log.verbosity(m.occurrences_of("verbosity") as usize);
|
||||
@ -167,4 +157,45 @@ impl Config {
|
||||
eprintln!("{:?}", config);
|
||||
config
|
||||
}
|
||||
|
||||
pub fn cookie_getter(&self) -> Arc<CookieGetter> {
|
||||
if let Some(ref value) = self.cookie {
|
||||
Arc::new(StaticCookie {
|
||||
value: value.clone(),
|
||||
})
|
||||
} else {
|
||||
Arc::new(CookieFile {
|
||||
daemon_dir: self.daemon_dir.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct StaticCookie {
|
||||
value: String,
|
||||
}
|
||||
|
||||
impl CookieGetter for StaticCookie {
|
||||
fn get(&self) -> String {
|
||||
self.value.clone()
|
||||
}
|
||||
}
|
||||
|
||||
struct CookieFile {
|
||||
daemon_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl CookieGetter for CookieFile {
|
||||
fn get(&self) -> String {
|
||||
read_cookie(&self.daemon_dir).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn read_cookie(daemon_dir: &Path) -> Result<String> {
|
||||
let mut path = daemon_dir.to_path_buf();
|
||||
path.push(".cookie");
|
||||
let contents = String::from_utf8(
|
||||
fs::read(&path).chain_err(|| format!("failed to read cookie from {:?}", path))?
|
||||
).chain_err(|| "invalid cookie string")?;
|
||||
Ok(contents.trim().to_owned())
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use std::collections::HashSet;
|
||||
use std::io::{BufRead, BufReader, Lines, Write};
|
||||
use std::net::{SocketAddr, TcpStream};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use metrics::{HistogramOpts, HistogramVec, Metrics};
|
||||
use util::HeaderList;
|
||||
@ -125,10 +125,14 @@ impl MempoolEntry {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CookieGetter: Send + Sync {
|
||||
fn get(&self) -> String;
|
||||
}
|
||||
|
||||
struct Connection {
|
||||
tx: TcpStream,
|
||||
rx: Lines<BufReader<TcpStream>>,
|
||||
cookie_b64: String,
|
||||
cookie_getter: Arc<CookieGetter>,
|
||||
addr: SocketAddr,
|
||||
}
|
||||
|
||||
@ -138,14 +142,14 @@ fn tcp_connect(addr: SocketAddr) -> Result<TcpStream> {
|
||||
}
|
||||
|
||||
impl Connection {
|
||||
fn new(addr: SocketAddr, cookie_b64: String) -> Result<Connection> {
|
||||
fn new(addr: SocketAddr, cookie_getter: Arc<CookieGetter>) -> Result<Connection> {
|
||||
let conn = tcp_connect(addr)?;
|
||||
let reader = BufReader::new(conn.try_clone()
|
||||
.chain_err(|| format!("failed to clone {:?}", conn))?);
|
||||
Ok(Connection {
|
||||
tx: conn,
|
||||
rx: reader.lines(),
|
||||
cookie_b64,
|
||||
cookie_getter,
|
||||
addr,
|
||||
})
|
||||
}
|
||||
@ -157,15 +161,16 @@ impl Connection {
|
||||
Ok(Connection {
|
||||
tx: conn,
|
||||
rx: reader.lines(),
|
||||
cookie_b64: self.cookie_b64.clone(),
|
||||
cookie_getter: self.cookie_getter.clone(),
|
||||
addr: self.addr,
|
||||
})
|
||||
}
|
||||
|
||||
fn send(&mut self, request: &str) -> Result<()> {
|
||||
let cookie_b64 = base64::encode(&self.cookie_getter.get());
|
||||
let msg = format!(
|
||||
"POST / HTTP/1.1\nAuthorization: Basic {}\nContent-Length: {}\n\n{}",
|
||||
self.cookie_b64,
|
||||
cookie_b64,
|
||||
request.len(),
|
||||
request,
|
||||
);
|
||||
@ -231,14 +236,14 @@ impl Daemon {
|
||||
pub fn new(
|
||||
daemon_dir: &PathBuf,
|
||||
daemon_rpc_addr: SocketAddr,
|
||||
cookie: &str,
|
||||
cookie_getter: Arc<CookieGetter>,
|
||||
network: Network,
|
||||
metrics: &Metrics,
|
||||
) -> Result<Daemon> {
|
||||
let daemon = Daemon {
|
||||
daemon_dir: daemon_dir.clone(),
|
||||
network,
|
||||
conn: Mutex::new(Connection::new(daemon_rpc_addr, base64::encode(cookie))?),
|
||||
conn: Mutex::new(Connection::new(daemon_rpc_addr, cookie_getter)?),
|
||||
message_id: Counter::new(),
|
||||
latency: metrics.histogram_vec(
|
||||
HistogramOpts::new("daemon_rpc", "Bitcoind RPC latency (in seconds)"),
|
||||
|
Loading…
Reference in New Issue
Block a user