diff --git a/crates/lb/src/net.rs b/crates/lb/src/net.rs index f5fe64d..23f500c 100644 --- a/crates/lb/src/net.rs +++ b/crates/lb/src/net.rs @@ -6,7 +6,10 @@ //! See [`lb_netlib`] for items exported by this library. use derive_more::{From, FromStr}; use luaffi::{cdef, metatype}; -use std::net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; +use std::{ + net::{AddrParseError, IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}, + time::Duration, +}; use thiserror::Error; use tokio::net::{TcpListener, TcpSocket, TcpStream}; @@ -99,39 +102,66 @@ impl lb_netlib { /// If `port` is not specified, `0` is used as the default. pub extern "Lua" fn socketaddr(&self, s: any, port: any) -> Result { if port != () { - self.__new_socketaddr(self.ipaddr(s), port) + self.__new_skaddr(self.ipaddr(s), port) } else { if __istype(__ct.lb_socketaddr, s) { __new(__ct.lb_socketaddr, s) // copy constructor } else if __istype(__ct.lb_ipaddr, s) { - self.__new_socketaddr(s, 0) // default port 0 + self.__new_skaddr(s, 0) // default port 0 } else { - self.__parse_socketaddr(s) + self.__parse_skaddr(s) } } } - extern "Lua-C" fn __new_socketaddr(&self, ip: &lb_ipaddr, port: u16) -> lb_socketaddr { + extern "Lua-C" fn __new_skaddr(&self, ip: &lb_ipaddr, port: u16) -> lb_socketaddr { SocketAddr::new(ip.0, port).into() } - extern "Lua-C" fn __parse_socketaddr(&self, s: &str) -> Result { + extern "Lua-C" fn __parse_skaddr(&self, s: &str) -> Result { Ok(s.parse()?) } /// Creates a new TCP socket configured for IPv4. /// /// See [`TcpSocket::new_v4`]. - pub extern "Lua-C" fn tcp_v4(&self) -> Result { + pub extern "Lua-C" fn tcp(&self) -> Result { Ok(Some(TcpSocket::new_v4()?).into()) } /// Creates a new TCP socket configured for IPv6. /// /// See [`TcpSocket::new_v6`]. - pub extern "Lua-C" fn tcp_v6(&self) -> Result { + pub extern "Lua-C" fn tcp6(&self) -> Result { Ok(Some(TcpSocket::new_v6()?).into()) } + + pub extern "Lua" fn bind_tcp(&self, addr: any, port: any) -> Result { + let addr = self.socketaddr(addr, port); + let socket; + if addr.ip().is_v6() { + socket = self.tcp6(); + } else { + socket = self.tcp(); + } + socket.bind(addr); + socket + } + + pub extern "Lua" fn connect_tcp(&self, addr: any, port: any) -> Result { + let addr = self.socketaddr(addr, port); + let socket; + if addr.ip().is_v6() { + socket = self.tcp6(); + } else { + socket = self.tcp(); + } + socket.connect(addr) + } + + pub extern "Lua" fn listen_tcp(&self, addr: any, port: any) -> Result { + self.bind_tcp(addr, port).listen(1024) + } } /// An IP address, either IPv4 or IPv6. @@ -322,8 +352,116 @@ pub struct lb_tcpsocket(#[opaque] Option); #[metatype] impl lb_tcpsocket { + fn socket(&self) -> Result<&TcpSocket> { + self.0.as_ref().ok_or(Error::SocketConsumed) + } + + /// See [`TcpSocket::keepalive`]. pub extern "Lua-C" fn keepalive(&self) -> Result { - todo!() + Ok(self.socket()?.keepalive()?) + } + + /// See [`TcpSocket::set_keepalive`]. + pub extern "Lua-C" fn set_keepalive(&self, enabled: bool) -> Result<()> { + Ok(self.socket()?.set_keepalive(enabled)?) + } + + /// See [`TcpSocket::reuseaddr`]. + pub extern "Lua-C" fn reuseaddr(&self) -> Result { + Ok(self.socket()?.reuseaddr()?) + } + + /// See [`TcpSocket::set_reuseaddr`]. + pub extern "Lua-C" fn set_reuseaddr(&self, enabled: bool) -> Result<()> { + Ok(self.socket()?.set_reuseaddr(enabled)?) + } + + /// See [`TcpSocket::reuseport`]. + pub extern "Lua-C" fn reuseport(&self) -> Result { + Ok(self.socket()?.reuseport()?) + } + + /// See [`TcpSocket::set_reuseport`]. + pub extern "Lua-C" fn set_reuseport(&self, enabled: bool) -> Result<()> { + Ok(self.socket()?.set_reuseport(enabled)?) + } + + /// See [`TcpSocket::send_buffer_size`]. + pub extern "Lua-C" fn sendbuf(&self) -> Result { + Ok(self.socket()?.send_buffer_size()?) + } + + /// See [`TcpSocket::set_send_buffer_size`]. + pub extern "Lua-C" fn set_sendbuf(&self, size: u32) -> Result<()> { + Ok(self.socket()?.set_send_buffer_size(size)?) + } + + /// See [`TcpSocket::recv_buffer_size`]. + pub extern "Lua-C" fn recvbuf(&self) -> Result { + Ok(self.socket()?.recv_buffer_size()?) + } + + /// See [`TcpSocket::set_recv_buffer_size`]. + pub extern "Lua-C" fn set_recvbuf(&self, size: u32) -> Result<()> { + Ok(self.socket()?.set_recv_buffer_size(size)?) + } + + /// See [`TcpSocket::linger`]. + pub extern "Lua-C" fn linger(&self) -> Result { + Ok(self + .socket()? + .linger()? + .map(|n| n.as_secs_f64()) + .unwrap_or(0.)) + } + + /// See [`TcpSocket::set_linger`]. + pub extern "Lua-C" fn set_linger(&self, secs: f64) -> Result<()> { + Ok(self + .socket()? + .set_linger((secs != 0.).then_some(Duration::from_secs_f64(secs)))?) + } + + /// See [`TcpSocket::nodelay`]. + pub extern "Lua-C" fn nodelay(&self) -> Result { + Ok(self.socket()?.nodelay()?) + } + + /// See [`TcpSocket::set_nodelay`]. + pub extern "Lua-C" fn set_nodelay(&self, enabled: bool) -> Result<()> { + Ok(self.socket()?.set_nodelay(enabled)?) + } + + /// See [`TcpSocket::tos`]. + pub extern "Lua-C" fn tos(&self) -> Result { + Ok(self.socket()?.tos()?) + } + + /// See [`TcpSocket::set_tos`]. + pub extern "Lua-C" fn set_tos(&self, tos: u32) -> Result<()> { + Ok(self.socket()?.set_tos(tos)?) + } + + /// See [`TcpSocket::local_addr`]. + pub extern "Lua-C" fn local_addr(&self) -> Result { + Ok(self.socket()?.local_addr()?.into()) + } + + /// See [`TcpSocket::bind`]. + pub extern "Lua-C" fn bind(&self, addr: &lb_socketaddr) -> Result<()> { + Ok(self.socket()?.bind(addr.0)?) + } + + /// See [`TcpSocket::connect`]. + pub async extern "Lua-C" fn connect(&mut self, addr: &lb_socketaddr) -> Result { + let socket = self.0.take().ok_or(Error::SocketConsumed)?; + Ok(socket.connect(addr.0).await?.into()) + } + + /// See [`TcpSocket::listen`]. + pub extern "Lua-C" fn listen(&mut self, backlog: u32) -> Result { + let socket = self.0.take().ok_or(Error::SocketConsumed)?; + Ok(socket.listen(backlog)?.into()) } }