use std::ffi::CString;
use crate::error::{Error, ErrorKind, Result};
use crate::socket::Socket;
pub struct Dialer
{
handle: nng_sys::nng_dialer,
}
impl Dialer
{
pub fn new(socket: &Socket, url: &str, nonblocking: bool) -> Result<Self>
{
let addr = CString::new(url).map_err(|_| ErrorKind::AddressInvalid)?;
let mut handle = nng_sys::NNG_DIALER_INITIALIZER;
let flags = if nonblocking { nng_sys::NNG_FLAG_NONBLOCK } else { 0 };
let rv = unsafe {
nng_sys::nng_dial(socket.handle(), addr.as_ptr(), &mut handle as *mut _, flags)
};
rv2res!(rv, Dialer { handle })
}
pub fn id(&self) -> i32
{
let id = unsafe { nng_sys::nng_dialer_id(self.handle) };
assert!(id > 0, "Invalid dialer ID returned from valid socket");
id
}
}
expose_options!{
Dialer :: handle -> nng_sys::nng_dialer;
GETOPT_BOOL = nng_sys::nng_dialer_getopt_bool;
GETOPT_INT = nng_sys::nng_dialer_getopt_int;
GETOPT_MS = nng_sys::nng_dialer_getopt_ms;
GETOPT_SIZE = nng_sys::nng_dialer_getopt_size;
GETOPT_SOCKADDR = nng_sys::nng_dialer_getopt_sockaddr;
GETOPT_STRING = nng_sys::nng_dialer_getopt_string;
SETOPT = nng_sys::nng_dialer_setopt;
SETOPT_BOOL = nng_sys::nng_dialer_setopt_bool;
SETOPT_INT = nng_sys::nng_dialer_setopt_int;
SETOPT_MS = nng_sys::nng_dialer_setopt_ms;
SETOPT_SIZE = nng_sys::nng_dialer_setopt_size;
SETOPT_STRING = nng_sys::nng_dialer_setopt_string;
Gets -> [LocalAddr, Raw, ReconnectMinTime,
ReconnectMaxTime, RecvBufferSize,
RecvMaxSize, RecvTimeout,
SendBufferSize, SendTimeout,
SocketName, MaxTtl, Url,
protocol::reqrep::ResendTime,
protocol::survey::SurveyTime,
transport::tcp::NoDelay,
transport::tcp::KeepAlive];
Sets -> [];
}
impl Drop for Dialer
{
fn drop(&mut self)
{
let rv = unsafe { nng_sys::nng_dialer_close(self.handle) };
assert!(
rv == 0 || rv == nng_sys::NNG_ECLOSED,
"Unexpected error code while closing dialer ({})", rv
);
}
}
pub struct DialerOptions
{
handle: nng_sys::nng_dialer,
}
impl DialerOptions
{
pub fn new(socket: &Socket, url: &str) -> Result<Self>
{
let addr = CString::new(url).map_err(|_| ErrorKind::AddressInvalid)?;
let mut handle = nng_sys::NNG_DIALER_INITIALIZER;
let rv = unsafe { nng_sys::nng_dialer_create(&mut handle as *mut _, socket.handle(), addr.as_ptr()) };
rv2res!(rv, DialerOptions { handle })
}
pub fn start(self, nonblocking: bool) -> std::result::Result<Dialer, (Self, Error)>
{
let flags = if nonblocking { nng_sys::NNG_FLAG_NONBLOCK } else { 0 };
let rv = unsafe {
nng_sys::nng_dialer_start(self.handle, flags)
};
match rv {
0 => {
let handle = Dialer { handle: self.handle };
std::mem::forget(self);
Ok(handle)
},
e => Err((self, ErrorKind::from_code(e).into())),
}
}
}
expose_options!{
DialerOptions :: handle -> nng_sys::nng_dialer;
GETOPT_BOOL = nng_sys::nng_dialer_getopt_bool;
GETOPT_INT = nng_sys::nng_dialer_getopt_int;
GETOPT_MS = nng_sys::nng_dialer_getopt_ms;
GETOPT_SIZE = nng_sys::nng_dialer_getopt_size;
GETOPT_SOCKADDR = nng_sys::nng_dialer_getopt_sockaddr;
GETOPT_STRING = nng_sys::nng_dialer_getopt_string;
SETOPT = nng_sys::nng_dialer_setopt;
SETOPT_BOOL = nng_sys::nng_dialer_setopt_bool;
SETOPT_INT = nng_sys::nng_dialer_setopt_int;
SETOPT_MS = nng_sys::nng_dialer_setopt_ms;
SETOPT_SIZE = nng_sys::nng_dialer_setopt_size;
SETOPT_STRING = nng_sys::nng_dialer_setopt_string;
Gets -> [LocalAddr, Raw, ReconnectMinTime,
ReconnectMaxTime, RecvBufferSize,
RecvMaxSize, RecvTimeout,
SendBufferSize, SendTimeout,
SocketName, MaxTtl, Url,
protocol::reqrep::ResendTime,
protocol::survey::SurveyTime,
transport::tcp::NoDelay,
transport::tcp::KeepAlive];
Sets -> [ReconnectMinTime, ReconnectMaxTime,
RecvMaxSize, transport::tcp::NoDelay,
transport::tcp::KeepAlive,
transport::tls::CaFile,
transport::tls::CertKeyFile,
transport::websocket::RequestHeaders];
}
impl Drop for DialerOptions
{
fn drop(&mut self)
{
let rv = unsafe { nng_sys::nng_dialer_close(self.handle) };
assert!(
rv == 0 || rv == nng_sys::NNG_ECLOSED,
"Unexpected error code while closing dialer ({})", rv
);
}
}