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
14pub 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}