bwk_electrum/raw_client/
mod.rs

1pub(crate) mod ssl_client;
2pub(crate) mod tcp_client;
3
4use std::{collections::HashMap, fmt::Display, net, thread, time::Duration};
5
6use crate::electrum::{
7    self,
8    request::Request,
9    response::{parse_str_response, Response},
10};
11
12use self::{ssl_client::SslClient, tcp_client::TcpClient};
13
14// Using a 1 byte seek buffer
15pub const PEEK_BUFFER_SIZE: usize = 10;
16
17#[derive(Debug)]
18pub enum Error {
19    TcpStream(std::io::Error),
20    SslStream(openssl::ssl::HandshakeError<net::TcpStream>),
21    Electrum(electrum::Error),
22    SslPeek,
23    Mutex,
24    SslConnector(std::io::Error),
25    AlreadyConnected,
26    NotConnected,
27    NotConfigured,
28    ShutDown,
29    SetNonBlocking,
30    SetBlocking,
31    SerializeRequest,
32    Batch,
33}
34
35impl Display for Error {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        write!(f, "{:?}", self)
38    }
39}
40
41impl From<electrum::Error> for Error {
42    fn from(value: electrum::Error) -> Self {
43        Error::Electrum(value)
44    }
45}
46
47#[derive(Debug, Default, Clone)]
48pub enum Client {
49    #[default]
50    None,
51    Tcp(TcpClient),
52    Ssl(SslClient),
53}
54
55impl Drop for Client {
56    fn drop(&mut self) {
57        let _ = self.close();
58    }
59}
60
61impl Client {
62    pub fn new() -> Self {
63        Self::default()
64    }
65
66    pub fn tcp(self, url: &str, port: u16) -> Self {
67        Self::new_tcp(url, port)
68    }
69
70    pub fn new_tcp(url: &str, port: u16) -> Self {
71        Self::Tcp(TcpClient::default().url(url).port(port))
72    }
73
74    pub fn ssl(self, url: &str, port: u16) -> Self {
75        Self::new_ssl(url, port)
76    }
77
78    pub fn new_ssl(url: &str, port: u16) -> Self {
79        Self::Ssl(SslClient::default().url(url).port(port))
80    }
81
82    pub fn new_ssl_maybe(url: &str, port: u16, ssl: bool) -> Self {
83        match ssl {
84            true => Self::new_ssl(url, port),
85            false => Self::new_tcp(url, port),
86        }
87    }
88
89    pub fn read_timeout(mut self, timeout: Option<Duration>) -> Self {
90        match &mut self {
91            Client::None => {}
92            Client::Tcp(c) => c.read_timeout = timeout,
93            Client::Ssl(c) => c.read_timeout = timeout,
94        }
95        self
96    }
97
98    pub fn set_read_timeout(&mut self, timeout: Option<Duration>) -> Result<(), Error> {
99        match self {
100            Client::None => Err(Error::NotConfigured),
101            Client::Tcp(c) => c.set_read_timeout(timeout),
102            Client::Ssl(c) => c.set_read_timeout(timeout),
103        }
104    }
105
106    pub fn write_timeout(mut self, timeout: Option<Duration>) -> Self {
107        match &mut self {
108            Client::None => {}
109            Client::Tcp(c) => c.write_timeout = timeout,
110            Client::Ssl(c) => c.write_timeout = timeout,
111        }
112        self
113    }
114
115    pub fn set_write_timeout(&mut self, timeout: Option<Duration>) -> Result<(), Error> {
116        match self {
117            Client::None => Err(Error::NotConfigured),
118            Client::Tcp(c) => c.set_write_timeout(timeout),
119            Client::Ssl(c) => c.set_write_timeout(timeout),
120        }
121    }
122
123    pub fn verif_certificate(mut self, verif: bool) -> Self {
124        let connected = self.is_connected();
125        if let (
126            Self::Ssl(SslClient {
127                verif_certificate, ..
128            }),
129            false,
130        ) = (&mut self, connected)
131        {
132            *verif_certificate = verif;
133        }
134        self
135    }
136
137    pub fn connect(&mut self) {
138        self.try_connect().unwrap()
139    }
140
141    pub fn is_connected(&self) -> bool {
142        match self {
143            Client::None => false,
144            Client::Tcp(c) => c.is_connected(),
145            Client::Ssl(c) => c.is_connected(),
146        }
147    }
148
149    pub fn try_connect(&mut self) -> Result<(), Error> {
150        match self {
151            Client::None => Err(Error::NotConfigured),
152            Client::Tcp(c) => c.try_connect(),
153            Client::Ssl(c) => c.try_connect(),
154        }
155    }
156
157    pub fn try_connect_retry(&mut self, retry: usize, delay: Duration) -> Result<(), Error> {
158        let mut result = self.try_connect();
159        let mut count = 0;
160        loop {
161            match result {
162                e @ Err(Error::NotConfigured) => return e,
163                e @ Err(_) => {
164                    thread::sleep(delay);
165                    count += 1;
166                    if count > retry {
167                        return e;
168                    }
169                    result = self.try_connect();
170                }
171                ok => return ok,
172            }
173        }
174    }
175
176    pub fn send(&mut self, request: &Request) {
177        self.try_send(request).unwrap();
178    }
179
180    pub fn send_str(&mut self, request: &str) {
181        self.try_send_str(request).unwrap();
182    }
183
184    pub fn try_send_batch(&mut self, requests: Vec<&Request>) -> Result<(), Error> {
185        let batch = serde_json::to_string(&requests).map_err(|_| Error::Batch)?;
186        self.try_send_str(&batch)
187    }
188
189    pub fn try_send(&mut self, request: &Request) -> Result<(), Error> {
190        let s = serde_json::to_string(request).map_err(|_| Error::SerializeRequest)?;
191        self.try_send_str(&s)
192    }
193
194    pub fn try_send_str(&mut self, request: &str) -> Result<(), Error> {
195        match self {
196            Client::None => Err(Error::NotConfigured),
197            Client::Tcp(c) => {
198                if let Some(stream) = c.stream.as_mut() {
199                    let mut stream = stream.lock().map_err(|_| Error::Mutex)?;
200                    TcpClient::send(&mut stream, request)
201                } else {
202                    Err(Error::NotConnected)
203                }
204            }
205            Client::Ssl(c) => {
206                if let Some(stream) = c.stream.as_mut() {
207                    let mut stream = stream.lock().map_err(|_| Error::Mutex)?;
208                    SslClient::send(&mut stream, request)
209                } else {
210                    Err(Error::NotConnected)
211                }
212            }
213        }
214    }
215
216    pub fn recv(&mut self, index: &HashMap<usize, Request>) -> Result<Vec<Response>, Error> {
217        let raw = self.recv_str()?;
218        Ok(parse_str_response(&raw, index)?)
219    }
220
221    pub fn recv_str(&mut self) -> Result<String, Error> {
222        match self {
223            Client::None => Err(Error::NotConfigured),
224            Client::Tcp(c) => {
225                if let Some(stream) = c.stream.as_mut() {
226                    let mut stream = stream.lock().map_err(|_| Error::Mutex)?;
227                    TcpClient::read(&mut stream)
228                } else {
229                    Err(Error::NotConnected)
230                }
231            }
232            Client::Ssl(c) => {
233                if let Some(stream) = c.stream.as_mut() {
234                    let mut stream = stream.lock().map_err(|_| Error::Mutex)?;
235                    SslClient::read(&mut stream)
236                } else {
237                    Err(Error::NotConnected)
238                }
239            }
240        }
241    }
242
243    pub fn try_recv(
244        &mut self,
245        index: &HashMap<usize, Request>,
246    ) -> Result<Option<Vec<Response>>, Error> {
247        let raw = self.try_recv_str()?;
248        if let Some(rr) = raw {
249            Ok(Some(parse_str_response(&rr, index)?))
250        } else {
251            Ok(None)
252        }
253    }
254
255    pub fn try_recv_str(&mut self) -> Result<Option<String>, Error> {
256        match self {
257            Client::None => Err(Error::NotConfigured),
258            Client::Tcp(c) => {
259                if let Some(stream) = c.stream.as_mut() {
260                    let mut stream = stream.lock().map_err(|_| Error::Mutex)?;
261                    TcpClient::try_read(&mut stream)
262                } else {
263                    Err(Error::NotConnected)
264                }
265            }
266            Client::Ssl(c) => {
267                if let Some(stream) = c.stream.as_mut() {
268                    let mut stream = stream.lock().map_err(|_| Error::Mutex)?;
269                    SslClient::try_read(&mut stream)
270                } else {
271                    Err(Error::NotConnected)
272                }
273            }
274        }
275    }
276
277    pub fn close(&mut self) -> Result<(), Error> {
278        match self {
279            Client::None => Ok(()),
280            Client::Tcp(c) => c.close(),
281            Client::Ssl(c) => c.close(),
282        }
283    }
284}