use core::net::{IpAddr, SocketAddr};
use std::sync::Arc;
use pyo3::{Python, pyclass, pymethods};
use pyo3_async_runtimes::tokio::future_into_py;
use crate::{PyFut, ip_or_str::IpRepr, py_value_err, sockaddr_as_tuple};
#[pyclass(frozen, module = "_internal")]
pub struct UdpSocket {
pub(crate) sock: Arc<ts::UdpSocket>,
}
#[pymethods]
impl UdpSocket {
pub fn sendto<'p>(&self, py: Python<'p>, addr: (IpRepr, u16), msg: &[u8]) -> PyFut<'p> {
let (ip, port) = addr;
let addr = ip.try_into()?;
let socket_addr = SocketAddr::new(addr, port);
let msg = msg.to_vec();
let sock = self.sock.clone();
let none = py.None();
future_into_py(py, async move {
sock.send_to(socket_addr, &msg)
.await
.map_err(py_value_err)?;
Ok(none)
})
}
pub fn recvfrom<'p>(&self, py: Python<'p>) -> PyFut<'p> {
let sock = self.sock.clone();
future_into_py(py, async move {
let (who, msg) = sock.recv_from_bytes().await.map_err(py_value_err)?;
Ok((msg, (who.ip(), who.port())))
})
}
pub fn local_addr(&self) -> (IpAddr, u16) {
sockaddr_as_tuple(self.sock.local_addr())
}
fn __repr__(&self) -> String {
format!("tailscale.UdpSocket({})", self.sock.local_addr())
}
}