use std::io::{Read, Write};
use std::mem;
use std::net::TcpStream;
use std::os::unix::net::UnixStream;
use std::path::Path;
use crate::common::util::status::*;
const NUM_CONNECT_ATTEMPTS: usize = 10;
const CONNECT_TIMEOUT_MS: u64 = 1000;
fn connect_ipc_socket(pathname: &str) -> Result<UnixStream> {
let socket = Path::new(pathname);
match UnixStream::connect(&socket) {
Err(e) => {
return Err(VineyardError::io_error(format!(
"Failed to connect to {:?}. {}",
socket, e
)));
}
Ok(stream) => {
return Ok(stream);
}
};
}
fn connect_rpc_endpoint(host: &str, port: u16) -> Result<TcpStream> {
match TcpStream::connect(format!("{}:{}", host, port)) {
Err(e) => {
return Err(VineyardError::io_error(format!(
"Failed to connect to {}:{}. {}",
host, port, e
)));
}
Ok(stream) => {
return Ok(stream);
}
};
}
pub fn connect_ipc_socket_retry(pathname: &str) -> Result<UnixStream> {
let mut i = 0;
loop {
match connect_ipc_socket(pathname) {
Err(e) => {
if i < NUM_CONNECT_ATTEMPTS {
i += 1;
info!(
concat!(
"Connection to IPC socket failed for pathname {} ",
"with ret = {}, retrying {} more times."
),
pathname,
e,
NUM_CONNECT_ATTEMPTS - i
);
std::thread::sleep(std::time::Duration::from_millis(CONNECT_TIMEOUT_MS));
continue;
} else {
return Err(e);
}
}
Ok(stream) => {
return Ok(stream);
}
}
}
}
pub fn connect_rpc_endpoint_retry(host: &str, port: u16) -> Result<TcpStream> {
let mut i = 0;
loop {
match connect_rpc_endpoint(host, port) {
Err(e) => {
if i < NUM_CONNECT_ATTEMPTS {
i += 1;
info!(
concat!(
"Connection to RPC socket failed for endpoint {}:{} ",
"with ret = {}, retrying {} more times."
),
host,
port,
e,
NUM_CONNECT_ATTEMPTS - i
);
std::thread::sleep(std::time::Duration::from_millis(CONNECT_TIMEOUT_MS));
continue;
} else {
return Err(e);
}
}
Ok(stream) => {
return Ok(stream);
}
}
}
}
fn recv_bytes<T: Read>(stream: &mut T, data: &mut [u8], length: usize) -> Result<()> {
let mut remaining = length;
let mut offset = 0;
while remaining > 0 {
let n = stream.read(&mut data[offset..])?;
remaining -= n;
offset += n;
}
Ok(())
}
fn recv_message<T: Read>(stream: &mut T) -> Result<String> {
let mut size_buf = [0u8; mem::size_of::<usize>()];
recv_bytes(stream, &mut size_buf, mem::size_of::<usize>())?;
let size = usize::from_le_bytes(size_buf);
let mut message_buf = vec![0u8; size];
recv_bytes(stream, message_buf.as_mut_slice(), size)?;
Ok(String::from_utf8(message_buf).unwrap())
}
fn send_bytes<T: Write>(stream: &mut T, data: &[u8], length: usize) -> Result<()> {
let mut remaining = length;
let mut offset = 0;
while remaining > 0 {
let n = stream.write(&data[offset..])?;
remaining -= n;
offset += n;
}
Ok(())
}
fn send_message<T: Write>(stream: &mut T, message: &str) -> Result<()> {
let len = message.len();
let bytes = len.to_le_bytes();
send_bytes(stream, &bytes, mem::size_of::<usize>())?;
send_bytes(stream, message.as_bytes(), len)?;
Ok(())
}
pub fn do_read<T: Read>(stream: &mut T) -> Result<String> {
return recv_message(stream);
}
pub fn do_write<T: Write>(stream: &mut T, message_out: &str) -> Result<()> {
return send_message(stream, message_out);
}