use std::ffi::CString;
use crate::error::{Error, ErrorKind, Result};
use crate::socket::Socket;
pub struct Listener
{
handle: nng_sys::nng_listener,
}
impl Listener
{
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_LISTENER_INITIALIZER;
let flags = if nonblocking { nng_sys::NNG_FLAG_NONBLOCK } else { 0 };
let rv = unsafe {
nng_sys::nng_listen(socket.handle(), addr.as_ptr(), &mut handle as *mut _, flags)
};
rv2res!(rv, Listener { handle })
}
pub fn id(&self) -> i32
{
let id = unsafe { nng_sys::nng_listener_id(self.handle) };
assert!(id > 0, "Invalid listener ID returned from valid socket");
id
}
}
expose_options!{
Listener :: handle -> nng_sys::nng_listener;
GETOPT_BOOL = nng_sys::nng_listener_getopt_bool;
GETOPT_INT = nng_sys::nng_listener_getopt_int;
GETOPT_MS = nng_sys::nng_listener_getopt_ms;
GETOPT_SIZE = nng_sys::nng_listener_getopt_size;
GETOPT_SOCKADDR = nng_sys::nng_listener_getopt_sockaddr;
GETOPT_STRING = nng_sys::nng_listener_getopt_string;
SETOPT = nng_sys::nng_listener_setopt;
SETOPT_BOOL = nng_sys::nng_listener_setopt_bool;
SETOPT_INT = nng_sys::nng_listener_setopt_int;
SETOPT_MS = nng_sys::nng_listener_setopt_ms;
SETOPT_SIZE = nng_sys::nng_listener_setopt_size;
SETOPT_STRING = nng_sys::nng_listener_setopt_string;
Gets -> [LocalAddr, Raw, RecvBufferSize,
RecvTimeout, SendBufferSize, Url,
SendTimeout, SocketName, MaxTtl,
protocol::reqrep::ResendTime,
protocol::survey::SurveyTime,
transport::tcp::NoDelay,
transport::tcp::KeepAlive];
Sets -> [];
}
impl Drop for Listener
{
fn drop(&mut self)
{
let rv = unsafe { nng_sys::nng_listener_close(self.handle) };
assert!(
rv == 0 || rv == nng_sys::NNG_ECLOSED,
"Unexpected error code while closing listener ({})", rv
);
}
}
pub struct ListenerOptions
{
handle: nng_sys::nng_listener,
}
impl ListenerOptions
{
pub fn new(socket: &Socket, url: &str) -> Result<Self>
{
let addr = CString::new(url).map_err(|_| ErrorKind::AddressInvalid)?;
let mut handle = nng_sys::NNG_LISTENER_INITIALIZER;
let rv = unsafe { nng_sys::nng_listener_create(&mut handle as *mut _, socket.handle(), addr.as_ptr()) };
rv2res!(rv, ListenerOptions { handle })
}
pub fn start(self, nonblocking: bool) -> std::result::Result<Listener, (Self, Error)>
{
let flags = if nonblocking { nng_sys::NNG_FLAG_NONBLOCK } else { 0 };
let rv = unsafe {
nng_sys::nng_listener_start(self.handle, flags)
};
match rv {
0 => {
let handle = Listener { handle: self.handle };
std::mem::forget(self);
Ok(handle)
},
e => Err((self, ErrorKind::from_code(e).into())),
}
}
}
expose_options!{
ListenerOptions :: handle -> nng_sys::nng_listener;
GETOPT_BOOL = nng_sys::nng_listener_getopt_bool;
GETOPT_INT = nng_sys::nng_listener_getopt_int;
GETOPT_MS = nng_sys::nng_listener_getopt_ms;
GETOPT_SIZE = nng_sys::nng_listener_getopt_size;
GETOPT_SOCKADDR = nng_sys::nng_listener_getopt_sockaddr;
GETOPT_STRING = nng_sys::nng_listener_getopt_string;
SETOPT = nng_sys::nng_listener_setopt;
SETOPT_BOOL = nng_sys::nng_listener_setopt_bool;
SETOPT_INT = nng_sys::nng_listener_setopt_int;
SETOPT_MS = nng_sys::nng_listener_setopt_ms;
SETOPT_SIZE = nng_sys::nng_listener_setopt_size;
SETOPT_STRING = nng_sys::nng_listener_setopt_string;
Gets -> [LocalAddr, Raw, RecvBufferSize,
RecvTimeout, SendBufferSize, Url,
SendTimeout, SocketName, MaxTtl,
protocol::reqrep::ResendTime,
protocol::survey::SurveyTime,
transport::tcp::NoDelay,
transport::tcp::KeepAlive];
Sets -> [RecvMaxSize, transport::tcp::NoDelay,
transport::tcp::KeepAlive,
transport::tls::CaFile,
transport::tls::CertKeyFile,
transport::websocket::ResponseHeaders];
}
impl Drop for ListenerOptions
{
fn drop(&mut self)
{
let rv = unsafe { nng_sys::nng_listener_close(self.handle) };
assert!(
rv == 0 || rv == nng_sys::NNG_ECLOSED,
"Unexpected error code while closing listener ({})", rv
);
}
}