netget/server/
socket_helpers.rs1use anyhow::Result;
4#[cfg(not(target_arch = "wasm32"))]
5use socket2::{Domain, Socket, Type};
6#[cfg(unix)]
7use std::net::Ipv4Addr;
8use std::net::SocketAddr;
9#[cfg(unix)]
10use std::os::unix::io::FromRawFd;
11use tokio::net::{TcpListener, UdpSocket};
12
13#[cfg(unix)]
15const IPPROTO_OSPF: i32 = 89;
16
17#[cfg(unix)]
19const OSPF_ALL_SPF_ROUTERS: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 5);
20
21#[cfg(unix)]
23const OSPF_ALL_DROUTERS: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 6);
24
25#[cfg(not(target_arch = "wasm32"))]
30pub async fn create_reusable_tcp_listener(addr: SocketAddr) -> Result<TcpListener> {
31 let socket = if addr.is_ipv4() {
32 Socket::new(Domain::IPV4, Type::STREAM, None)?
33 } else {
34 Socket::new(Domain::IPV6, Type::STREAM, None)?
35 };
36
37 socket.set_reuse_address(true)?;
39
40 socket.bind(&addr.into())?;
42
43 socket.listen(128)?;
45
46 socket.set_nonblocking(true)?;
48 let std_listener: std::net::TcpListener = socket.into();
49 let tokio_listener = TcpListener::from_std(std_listener)?;
50
51 Ok(tokio_listener)
52}
53
54#[cfg(not(target_arch = "wasm32"))]
58pub async fn create_reusable_udp_socket(addr: SocketAddr) -> Result<UdpSocket> {
59 let socket = if addr.is_ipv4() {
60 Socket::new(Domain::IPV4, Type::DGRAM, None)?
61 } else {
62 Socket::new(Domain::IPV6, Type::DGRAM, None)?
63 };
64
65 socket.set_reuse_address(true)?;
67
68 socket.bind(&addr.into())?;
70
71 socket.set_nonblocking(true)?;
73 let std_socket: std::net::UdpSocket = socket.into();
74 let tokio_socket = UdpSocket::from_std(std_socket)?;
75
76 Ok(tokio_socket)
77}
78
79#[cfg(target_arch = "wasm32")]
82pub async fn create_reusable_tcp_listener(addr: SocketAddr) -> Result<TcpListener> {
83 Ok(TcpListener::bind(addr).await?)
84}
85
86#[cfg(target_arch = "wasm32")]
88pub async fn create_reusable_udp_socket(addr: SocketAddr) -> Result<UdpSocket> {
89 Ok(UdpSocket::bind(addr).await?)
90}
91
92#[cfg(unix)]
105pub fn create_ospf_raw_socket(
106 interface_addr: Ipv4Addr,
107 join_all_routers: bool,
108 join_dr_routers: bool,
109) -> Result<Socket> {
110 let socket = unsafe {
113 let fd = libc::socket(libc::AF_INET, libc::SOCK_RAW, IPPROTO_OSPF);
114 if fd < 0 {
115 return Err(std::io::Error::last_os_error().into());
116 }
117 Socket::from_raw_fd(fd)
118 };
119
120 socket.set_nonblocking(true)?;
122
123 socket.set_reuse_address(true)?;
125
126 if join_all_routers {
128 socket.join_multicast_v4(&OSPF_ALL_SPF_ROUTERS, &interface_addr)?;
129 }
130
131 if join_dr_routers {
133 socket.join_multicast_v4(&OSPF_ALL_DROUTERS, &interface_addr)?;
134 }
135
136 socket.set_multicast_ttl_v4(1)?;
138
139 socket.set_multicast_loop_v4(true)?;
141
142 socket.set_multicast_if_v4(&interface_addr)?;
144
145 Ok(socket)
146}