Implement lb_tcpsocket

This commit is contained in:
lumi 2025-06-26 13:07:24 +10:00
parent 2fe9515702
commit bcb734846d
Signed by: luaneko
GPG Key ID: 406809B8763FF07A

View File

@ -6,7 +6,10 @@
//! See [`lb_netlib`] for items exported by this library. //! See [`lb_netlib`] for items exported by this library.
use derive_more::{From, FromStr}; use derive_more::{From, FromStr};
use luaffi::{cdef, metatype}; 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 thiserror::Error;
use tokio::net::{TcpListener, TcpSocket, TcpStream}; use tokio::net::{TcpListener, TcpSocket, TcpStream};
@ -99,39 +102,66 @@ impl lb_netlib {
/// If `port` is not specified, `0` is used as the default. /// If `port` is not specified, `0` is used as the default.
pub extern "Lua" fn socketaddr(&self, s: any, port: any) -> Result<lb_socketaddr> { pub extern "Lua" fn socketaddr(&self, s: any, port: any) -> Result<lb_socketaddr> {
if port != () { if port != () {
self.__new_socketaddr(self.ipaddr(s), port) self.__new_skaddr(self.ipaddr(s), port)
} else { } else {
if __istype(__ct.lb_socketaddr, s) { if __istype(__ct.lb_socketaddr, s) {
__new(__ct.lb_socketaddr, s) // copy constructor __new(__ct.lb_socketaddr, s) // copy constructor
} else if __istype(__ct.lb_ipaddr, s) { } else if __istype(__ct.lb_ipaddr, s) {
self.__new_socketaddr(s, 0) // default port 0 self.__new_skaddr(s, 0) // default port 0
} else { } 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() SocketAddr::new(ip.0, port).into()
} }
extern "Lua-C" fn __parse_socketaddr(&self, s: &str) -> Result<lb_socketaddr> { extern "Lua-C" fn __parse_skaddr(&self, s: &str) -> Result<lb_socketaddr> {
Ok(s.parse()?) Ok(s.parse()?)
} }
/// Creates a new TCP socket configured for IPv4. /// Creates a new TCP socket configured for IPv4.
/// ///
/// See [`TcpSocket::new_v4`]. /// See [`TcpSocket::new_v4`].
pub extern "Lua-C" fn tcp_v4(&self) -> Result<lb_tcpsocket> { pub extern "Lua-C" fn tcp(&self) -> Result<lb_tcpsocket> {
Ok(Some(TcpSocket::new_v4()?).into()) Ok(Some(TcpSocket::new_v4()?).into())
} }
/// Creates a new TCP socket configured for IPv6. /// Creates a new TCP socket configured for IPv6.
/// ///
/// See [`TcpSocket::new_v6`]. /// See [`TcpSocket::new_v6`].
pub extern "Lua-C" fn tcp_v6(&self) -> Result<lb_tcpsocket> { pub extern "Lua-C" fn tcp6(&self) -> Result<lb_tcpsocket> {
Ok(Some(TcpSocket::new_v6()?).into()) Ok(Some(TcpSocket::new_v6()?).into())
} }
pub extern "Lua" fn bind_tcp(&self, addr: any, port: any) -> Result<lb_tcpsocket> {
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<lb_tcpstream> {
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<lb_tcplistener> {
self.bind_tcp(addr, port).listen(1024)
}
} }
/// An IP address, either IPv4 or IPv6. /// An IP address, either IPv4 or IPv6.
@ -322,8 +352,116 @@ pub struct lb_tcpsocket(#[opaque] Option<TcpSocket>);
#[metatype] #[metatype]
impl lb_tcpsocket { 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<bool> { pub extern "Lua-C" fn keepalive(&self) -> Result<bool> {
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<bool> {
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<bool> {
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<u32> {
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<u32> {
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<f64> {
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<bool> {
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<u32> {
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<lb_socketaddr> {
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<lb_tcpstream> {
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<lb_tcplistener> {
let socket = self.0.take().ok_or(Error::SocketConsumed)?;
Ok(socket.listen(backlog)?.into())
} }
} }