fix: thread lock in tcp send/receive
This commit is contained in:
+37
-22
@@ -3,7 +3,7 @@ use std::{
|
|||||||
fmt,
|
fmt,
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
net::{IpAddr, SocketAddr, TcpStream},
|
net::{IpAddr, SocketAddr, TcpStream},
|
||||||
sync::{Mutex, OnceLock},
|
sync::{Arc, Mutex, OnceLock},
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -33,8 +33,7 @@ fn instances() -> &'static Mutex<HashMap<(IpAddr, u8), ()>> {
|
|||||||
|
|
||||||
pub struct DSP408 {
|
pub struct DSP408 {
|
||||||
connection: types::DeviceConnection,
|
connection: types::DeviceConnection,
|
||||||
socket: Option<TcpStream>,
|
socket: Arc<Mutex<Option<TcpStream>>>,
|
||||||
lock: Mutex<()>,
|
|
||||||
connected: bool,
|
connected: bool,
|
||||||
state: Option<types::DSPState>,
|
state: Option<types::DSPState>,
|
||||||
}
|
}
|
||||||
@@ -62,9 +61,7 @@ impl DSP408 {
|
|||||||
device_id,
|
device_id,
|
||||||
},
|
},
|
||||||
|
|
||||||
socket: None,
|
socket: Arc::new(Mutex::new(None)),
|
||||||
|
|
||||||
lock: Mutex::new(()),
|
|
||||||
|
|
||||||
connected: false,
|
connected: false,
|
||||||
|
|
||||||
@@ -72,19 +69,13 @@ impl DSP408 {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn send_raw(&mut self, data: &[u8]) -> Result<(), DSPError> {
|
fn send_raw(socket: &mut TcpStream, data: &[u8]) -> Result<(), DSPError> {
|
||||||
let _guard = self.lock.lock().unwrap();
|
|
||||||
|
|
||||||
let socket = self.socket.as_mut().ok_or(DSPError::NotConnected)?;
|
|
||||||
|
|
||||||
socket.write_all(data)?;
|
socket.write_all(data)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn recv_raw(&mut self) -> Result<Vec<u8>, DSPError> {
|
fn recv_raw(socket: &mut TcpStream) -> Result<Vec<u8>, DSPError> {
|
||||||
let socket = self.socket.as_mut().ok_or(DSPError::NotConnected)?;
|
|
||||||
|
|
||||||
let mut buffer = vec![0u8; RECV_BUFSIZE];
|
let mut buffer = vec![0u8; RECV_BUFSIZE];
|
||||||
|
|
||||||
match socket.read(&mut buffer) {
|
match socket.read(&mut buffer) {
|
||||||
@@ -101,10 +92,14 @@ impl DSP408 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_recv(&mut self, command: &[u8]) -> Result<types::DeviceResponseType, DSPError> {
|
pub fn send_recv(&self, command: &[u8]) -> Result<types::DeviceResponseType, DSPError> {
|
||||||
self.send_raw(command)?;
|
let mut socket_guard = self.socket.lock().unwrap();
|
||||||
|
|
||||||
let raw = self.recv_raw()?;
|
let socket = socket_guard.as_mut().ok_or(DSPError::NotConnected)?;
|
||||||
|
|
||||||
|
Self::send_raw(socket, command)?;
|
||||||
|
|
||||||
|
let raw = Self::recv_raw(socket)?;
|
||||||
|
|
||||||
let frame = extract_frame(&raw)?;
|
let frame = extract_frame(&raw)?;
|
||||||
|
|
||||||
@@ -117,6 +112,10 @@ impl DSP408 {
|
|||||||
self.connected
|
self.connected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn connection(&self) -> &types::DeviceConnection {
|
||||||
|
&self.connection
|
||||||
|
}
|
||||||
|
|
||||||
pub fn state(&self) -> Result<&types::DSPState, DSPError> {
|
pub fn state(&self) -> Result<&types::DSPState, DSPError> {
|
||||||
self.state.as_ref().ok_or(DSPError::NotConnected)
|
self.state.as_ref().ok_or(DSPError::NotConnected)
|
||||||
}
|
}
|
||||||
@@ -144,16 +143,31 @@ impl DSP408 {
|
|||||||
|
|
||||||
stream.set_read_timeout(Some(SOCKET_TIMEOUT))?;
|
stream.set_read_timeout(Some(SOCKET_TIMEOUT))?;
|
||||||
|
|
||||||
self.socket = Some(stream);
|
{
|
||||||
|
let mut socket = self.socket.lock().unwrap();
|
||||||
|
*socket = Some(stream);
|
||||||
|
}
|
||||||
|
|
||||||
let handshake = commands::build_handshake();
|
let handshake = commands::build_handshake();
|
||||||
|
|
||||||
self.send_raw(&handshake)?;
|
{
|
||||||
|
let mut socket = self.socket.lock().unwrap();
|
||||||
|
|
||||||
|
let socket = socket.as_mut().ok_or(DSPError::NotConnected)?;
|
||||||
|
|
||||||
|
Self::send_raw(socket, &handshake)?;
|
||||||
|
}
|
||||||
|
|
||||||
let start = std::time::Instant::now();
|
let start = std::time::Instant::now();
|
||||||
|
|
||||||
while start.elapsed() < SOCKET_TIMEOUT {
|
while start.elapsed() < SOCKET_TIMEOUT {
|
||||||
let raw = self.recv_raw()?;
|
let raw = {
|
||||||
|
let mut socket = self.socket.lock().unwrap();
|
||||||
|
|
||||||
|
let socket = socket.as_mut().ok_or(DSPError::NotConnected)?;
|
||||||
|
|
||||||
|
Self::recv_raw(socket)?
|
||||||
|
};
|
||||||
let frame = extract_frame(&raw)?;
|
let frame = extract_frame(&raw)?;
|
||||||
let response = map_response(&frame)?;
|
let response = map_response(&frame)?;
|
||||||
|
|
||||||
@@ -198,9 +212,10 @@ impl DSP408 {
|
|||||||
pub fn disconnect(&mut self) {
|
pub fn disconnect(&mut self) {
|
||||||
let key = (self.connection.host, self.connection.device_id);
|
let key = (self.connection.host, self.connection.device_id);
|
||||||
|
|
||||||
if let Some(mut socket) = self.socket.take() {
|
let mut socket_guard = self.socket.lock().unwrap();
|
||||||
let _ = socket.write_all(&commands::build_disconnect());
|
|
||||||
|
|
||||||
|
if let Some(mut socket) = socket_guard.take() {
|
||||||
|
let _ = socket.write_all(&commands::build_disconnect());
|
||||||
let _ = socket.shutdown(std::net::Shutdown::Both);
|
let _ = socket.shutdown(std::net::Shutdown::Both);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user