mirror of
https://gitlab.com/veilid/veilid.git
synced 2025-01-24 13:41:09 -05:00
fix windows
This commit is contained in:
parent
c9bf4260c5
commit
e729682804
@ -52,12 +52,12 @@ struct NetworkInner {
|
||||
wss_port: u16,
|
||||
interfaces: NetworkInterfaces,
|
||||
// udp
|
||||
bound_first_udp: BTreeMap<u16, (socket2::Socket, socket2::Socket)>,
|
||||
bound_first_udp: BTreeMap<u16, Option<(socket2::Socket, socket2::Socket)>>,
|
||||
inbound_udp_protocol_handlers: BTreeMap<SocketAddr, RawUdpProtocolHandler>,
|
||||
outbound_udpv4_protocol_handler: Option<RawUdpProtocolHandler>,
|
||||
outbound_udpv6_protocol_handler: Option<RawUdpProtocolHandler>,
|
||||
//tcp
|
||||
bound_first_tcp: BTreeMap<u16, (socket2::Socket, socket2::Socket)>,
|
||||
bound_first_tcp: BTreeMap<u16, Option<(socket2::Socket, socket2::Socket)>>,
|
||||
tls_acceptor: Option<TlsAcceptor>,
|
||||
listener_states: BTreeMap<SocketAddr, Arc<RwLock<ListenerState>>>,
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use super::sockets::*;
|
||||
use super::*;
|
||||
use crate::intf::*;
|
||||
use crate::network_connection::*;
|
||||
|
@ -1,3 +1,4 @@
|
||||
use super::sockets::*;
|
||||
use super::*;
|
||||
use futures_util::stream;
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
pub mod sockets;
|
||||
pub mod tcp;
|
||||
pub mod udp;
|
||||
pub mod wrtc;
|
||||
@ -6,7 +7,6 @@ pub mod ws;
|
||||
use crate::network_connection::*;
|
||||
use crate::xx::*;
|
||||
use crate::*;
|
||||
use socket2::{Domain, Protocol, Socket, Type};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ProtocolNetworkConnection {
|
||||
@ -85,141 +85,3 @@ impl ProtocolNetworkConnection {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_unbound_shared_udp_socket(domain: Domain) -> Result<socket2::Socket, String> {
|
||||
let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP))
|
||||
.map_err(|e| format!("Couldn't create UDP socket: {}", e))?;
|
||||
if domain == Domain::IPV6 {
|
||||
socket
|
||||
.set_only_v6(true)
|
||||
.map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?;
|
||||
}
|
||||
socket
|
||||
.set_reuse_address(true)
|
||||
.map_err(|e| format!("Couldn't set reuse address: {}", e))?;
|
||||
cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
socket.set_reuse_port(true).map_err(|e| format!("Couldn't set reuse port: {}", e))?;
|
||||
}
|
||||
}
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn new_bound_shared_udp_socket(local_address: SocketAddr) -> Result<socket2::Socket, String> {
|
||||
let domain = Domain::for_address(local_address);
|
||||
let socket = new_unbound_shared_udp_socket(domain)?;
|
||||
let socket2_addr = socket2::SockAddr::from(local_address);
|
||||
socket
|
||||
.bind(&socket2_addr)
|
||||
.map_err(|e| format!("failed to bind UDP socket: {}", e))?;
|
||||
|
||||
log_net!("created shared udp socket on {:?}", &local_address);
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn new_bound_first_udp_socket(local_address: SocketAddr) -> Result<socket2::Socket, String> {
|
||||
let domain = Domain::for_address(local_address);
|
||||
let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP))
|
||||
.map_err(|e| format!("Couldn't create UDP socket: {}", e))?;
|
||||
if domain == Domain::IPV6 {
|
||||
socket
|
||||
.set_only_v6(true)
|
||||
.map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?;
|
||||
}
|
||||
// Bind the socket -first- before turning on 'reuse address' this way it will
|
||||
// fail if the port is already taken
|
||||
let socket2_addr = socket2::SockAddr::from(local_address);
|
||||
socket
|
||||
.bind(&socket2_addr)
|
||||
.map_err(|e| format!("failed to bind UDP socket: {}", e))?;
|
||||
|
||||
// Set 'reuse address' so future binds to this port will succeed
|
||||
socket
|
||||
.set_reuse_address(true)
|
||||
.map_err(|e| format!("Couldn't set reuse address: {}", e))?;
|
||||
cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
socket.set_reuse_port(true).map_err(|e| format!("Couldn't set reuse port: {}", e))?;
|
||||
}
|
||||
}
|
||||
log_net!("created shared udp socket on {:?}", &local_address);
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn new_unbound_shared_tcp_socket(domain: Domain) -> Result<socket2::Socket, String> {
|
||||
let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!("failed to create TCP socket"))?;
|
||||
if let Err(e) = socket.set_linger(None) {
|
||||
log_net!(error "Couldn't set TCP linger: {}", e);
|
||||
}
|
||||
if let Err(e) = socket.set_nodelay(true) {
|
||||
log_net!(error "Couldn't set TCP nodelay: {}", e);
|
||||
}
|
||||
if domain == Domain::IPV6 {
|
||||
socket
|
||||
.set_only_v6(true)
|
||||
.map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?;
|
||||
}
|
||||
socket
|
||||
.set_reuse_address(true)
|
||||
.map_err(|e| format!("Couldn't set reuse address: {}", e))?;
|
||||
cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
socket.set_reuse_port(true).map_err(|e| format!("Couldn't set reuse port: {}", e))?;
|
||||
}
|
||||
}
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn new_bound_shared_tcp_socket(local_address: SocketAddr) -> Result<socket2::Socket, String> {
|
||||
let domain = Domain::for_address(local_address);
|
||||
|
||||
let socket = new_unbound_shared_tcp_socket(domain)?;
|
||||
|
||||
let socket2_addr = socket2::SockAddr::from(local_address);
|
||||
socket
|
||||
.bind(&socket2_addr)
|
||||
.map_err(|e| format!("failed to bind TCP socket: {}", e))?;
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn new_bound_first_tcp_socket(local_address: SocketAddr) -> Result<socket2::Socket, String> {
|
||||
let domain = Domain::for_address(local_address);
|
||||
|
||||
let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!("failed to create TCP socket"))?;
|
||||
if let Err(e) = socket.set_linger(None) {
|
||||
log_net!(error "Couldn't set TCP linger: {}", e);
|
||||
}
|
||||
if let Err(e) = socket.set_nodelay(true) {
|
||||
log_net!(error "Couldn't set TCP nodelay: {}", e);
|
||||
}
|
||||
if domain == Domain::IPV6 {
|
||||
socket
|
||||
.set_only_v6(true)
|
||||
.map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?;
|
||||
}
|
||||
// Bind the socket -first- before turning on 'reuse address' this way it will
|
||||
// fail if the port is already taken
|
||||
|
||||
let socket2_addr = socket2::SockAddr::from(local_address);
|
||||
socket
|
||||
.bind(&socket2_addr)
|
||||
.map_err(|e| format!("failed to bind TCP socket: {}", e))?;
|
||||
|
||||
// Set 'reuse address' so future binds to this port will succeed
|
||||
socket
|
||||
.set_reuse_address(true)
|
||||
.map_err(|e| format!("Couldn't set reuse address: {}", e))?;
|
||||
cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
socket.set_reuse_port(true).map_err(|e| format!("Couldn't set reuse port: {}", e))?;
|
||||
}
|
||||
}
|
||||
Ok(socket)
|
||||
}
|
||||
|
181
veilid-core/src/intf/native/network/protocol/sockets.rs
Normal file
181
veilid-core/src/intf/native/network/protocol/sockets.rs
Normal file
@ -0,0 +1,181 @@
|
||||
use crate::xx::*;
|
||||
use crate::*;
|
||||
use socket2::{Domain, Protocol, Socket, Type};
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(windows)] {
|
||||
use winapi::shared::ws2def::{ SOL_SOCKET, SO_EXCLUSIVEADDRUSE};
|
||||
use winapi::um::winsock2::{SOCKET_ERROR, setsockopt};
|
||||
use winapi::ctypes::c_int;
|
||||
use std::os::windows::io::AsRawSocket;
|
||||
|
||||
fn set_exclusiveaddruse(socket: &Socket) -> Result<(), String> {
|
||||
unsafe {
|
||||
let optval:c_int = 1;
|
||||
if setsockopt(socket.as_raw_socket().try_into().unwrap(), SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (&optval as *const c_int).cast(),
|
||||
std::mem::size_of::<c_int>() as c_int) == SOCKET_ERROR {
|
||||
return Err("Unable to SO_EXCLUSIVEADDRUSE".to_owned());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_unbound_shared_udp_socket(domain: Domain) -> Result<Socket, String> {
|
||||
let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP))
|
||||
.map_err(|e| format!("Couldn't create UDP socket: {}", e))?;
|
||||
if domain == Domain::IPV6 {
|
||||
socket
|
||||
.set_only_v6(true)
|
||||
.map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?;
|
||||
}
|
||||
socket
|
||||
.set_reuse_address(true)
|
||||
.map_err(|e| format!("Couldn't set reuse address: {}", e))?;
|
||||
cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
socket.set_reuse_port(true).map_err(|e| format!("Couldn't set reuse port: {}", e))?;
|
||||
}
|
||||
}
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn new_bound_shared_udp_socket(local_address: SocketAddr) -> Result<Socket, String> {
|
||||
let domain = Domain::for_address(local_address);
|
||||
let socket = new_unbound_shared_udp_socket(domain)?;
|
||||
let socket2_addr = socket2::SockAddr::from(local_address);
|
||||
socket.bind(&socket2_addr).map_err(|e| {
|
||||
format!(
|
||||
"failed to bind UDP socket to '{}' in domain '{:?}': {} ",
|
||||
local_address, domain, e
|
||||
)
|
||||
})?;
|
||||
|
||||
log_net!("created shared udp socket on {:?}", &local_address);
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn new_bound_first_udp_socket(local_address: SocketAddr) -> Result<Socket, String> {
|
||||
let domain = Domain::for_address(local_address);
|
||||
let socket = Socket::new(domain, Type::DGRAM, Some(Protocol::UDP))
|
||||
.map_err(|e| format!("Couldn't create UDP socket: {}", e))?;
|
||||
if domain == Domain::IPV6 {
|
||||
socket
|
||||
.set_only_v6(true)
|
||||
.map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?;
|
||||
}
|
||||
// Bind the socket -first- before turning on 'reuse address' this way it will
|
||||
// fail if the port is already taken
|
||||
let socket2_addr = socket2::SockAddr::from(local_address);
|
||||
|
||||
// On windows, do SO_EXCLUSIVEADDRUSE before the bind to ensure the port is fully available
|
||||
cfg_if! {
|
||||
if #[cfg(windows)] {
|
||||
set_exclusiveaddruse(&socket)?;
|
||||
}
|
||||
}
|
||||
|
||||
socket
|
||||
.bind(&socket2_addr)
|
||||
.map_err(|e| format!("failed to bind UDP socket: {}", e))?;
|
||||
|
||||
// Set 'reuse address' so future binds to this port will succeed
|
||||
// This does not work on Windows, where reuse options can not be set after the bind
|
||||
cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
socket
|
||||
.set_reuse_address(true)
|
||||
.map_err(|e| format!("Couldn't set reuse address: {}", e))?;
|
||||
socket.set_reuse_port(true).map_err(|e| format!("Couldn't set reuse port: {}", e))?;
|
||||
}
|
||||
}
|
||||
log_net!("created shared udp socket on {:?}", &local_address);
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn new_unbound_shared_tcp_socket(domain: Domain) -> Result<Socket, String> {
|
||||
let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!("failed to create TCP socket"))?;
|
||||
if let Err(e) = socket.set_linger(None) {
|
||||
log_net!(error "Couldn't set TCP linger: {}", e);
|
||||
}
|
||||
if let Err(e) = socket.set_nodelay(true) {
|
||||
log_net!(error "Couldn't set TCP nodelay: {}", e);
|
||||
}
|
||||
if domain == Domain::IPV6 {
|
||||
socket
|
||||
.set_only_v6(true)
|
||||
.map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?;
|
||||
}
|
||||
socket
|
||||
.set_reuse_address(true)
|
||||
.map_err(|e| format!("Couldn't set reuse address: {}", e))?;
|
||||
cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
socket.set_reuse_port(true).map_err(|e| format!("Couldn't set reuse port: {}", e))?;
|
||||
}
|
||||
}
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn new_bound_shared_tcp_socket(local_address: SocketAddr) -> Result<Socket, String> {
|
||||
let domain = Domain::for_address(local_address);
|
||||
|
||||
let socket = new_unbound_shared_tcp_socket(domain)?;
|
||||
|
||||
let socket2_addr = socket2::SockAddr::from(local_address);
|
||||
socket
|
||||
.bind(&socket2_addr)
|
||||
.map_err(|e| format!("failed to bind TCP socket: {}", e))?;
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub fn new_bound_first_tcp_socket(local_address: SocketAddr) -> Result<Socket, String> {
|
||||
let domain = Domain::for_address(local_address);
|
||||
|
||||
let socket = Socket::new(domain, Type::STREAM, Some(Protocol::TCP))
|
||||
.map_err(map_to_string)
|
||||
.map_err(logthru_net!("failed to create TCP socket"))?;
|
||||
if let Err(e) = socket.set_linger(None) {
|
||||
log_net!(error "Couldn't set TCP linger: {}", e);
|
||||
}
|
||||
if let Err(e) = socket.set_nodelay(true) {
|
||||
log_net!(error "Couldn't set TCP nodelay: {}", e);
|
||||
}
|
||||
if domain == Domain::IPV6 {
|
||||
socket
|
||||
.set_only_v6(true)
|
||||
.map_err(|e| format!("Couldn't set IPV6_V6ONLY: {}", e))?;
|
||||
}
|
||||
|
||||
// On windows, do SO_EXCLUSIVEADDRUSE before the bind to ensure the port is fully available
|
||||
cfg_if! {
|
||||
if #[cfg(windows)] {
|
||||
set_exclusiveaddruse(&socket)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Bind the socket -first- before turning on 'reuse address' this way it will
|
||||
// fail if the port is already taken
|
||||
let socket2_addr = socket2::SockAddr::from(local_address);
|
||||
socket
|
||||
.bind(&socket2_addr)
|
||||
.map_err(|e| format!("failed to bind TCP socket: {}", e))?;
|
||||
|
||||
// Set 'reuse address' so future binds to this port will succeed
|
||||
// This does not work on Windows, where reuse options can not be set after the bind
|
||||
cfg_if! {
|
||||
if #[cfg(unix)] {
|
||||
socket
|
||||
.set_reuse_address(true)
|
||||
.map_err(|e| format!("Couldn't set reuse address: {}", e))?;
|
||||
socket.set_reuse_port(true).map_err(|e| format!("Couldn't set reuse port: {}", e))?;
|
||||
}
|
||||
}
|
||||
Ok(socket)
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
use super::sockets::*;
|
||||
use super::*;
|
||||
use crate::intf::*;
|
||||
use crate::network_manager::MAX_MESSAGE_SIZE;
|
||||
@ -139,7 +140,9 @@ impl RawTcpProtocolHandler {
|
||||
// Make a shared socket
|
||||
let socket = match local_address {
|
||||
Some(a) => new_bound_shared_tcp_socket(a)?,
|
||||
None => new_unbound_shared_tcp_socket(Domain::for_address(remote_socket_addr))?,
|
||||
None => {
|
||||
new_unbound_shared_tcp_socket(socket2::Domain::for_address(remote_socket_addr))?
|
||||
}
|
||||
};
|
||||
|
||||
// Connect to the remote address
|
||||
|
@ -1,3 +1,4 @@
|
||||
use super::sockets::*;
|
||||
use super::*;
|
||||
use crate::intf::*;
|
||||
use crate::network_manager::MAX_MESSAGE_SIZE;
|
||||
@ -207,7 +208,9 @@ impl WebsocketProtocolHandler {
|
||||
// Make a shared socket
|
||||
let socket = match local_address {
|
||||
Some(a) => new_bound_shared_tcp_socket(a)?,
|
||||
None => new_unbound_shared_tcp_socket(Domain::for_address(remote_socket_addr))?,
|
||||
None => {
|
||||
new_unbound_shared_tcp_socket(socket2::Domain::for_address(remote_socket_addr))?
|
||||
}
|
||||
};
|
||||
|
||||
// Connect to the remote address
|
||||
|
@ -1,3 +1,4 @@
|
||||
use super::sockets::*;
|
||||
use super::*;
|
||||
|
||||
impl Network {
|
||||
@ -26,7 +27,18 @@ impl Network {
|
||||
}
|
||||
}
|
||||
if let (Some(bfs4), Some(bfs6)) = (bound_first_socket_v4, bound_first_socket_v6) {
|
||||
inner.bound_first_udp.insert(udp_port, (bfs4, bfs6));
|
||||
cfg_if! {
|
||||
if #[cfg(windows)] {
|
||||
// On windows, drop the socket. This is a race condition, but there's
|
||||
// no way around it. This isn't for security anyway, it's to prevent multiple copies of the
|
||||
// app from binding on the same port.
|
||||
drop(bfs4);
|
||||
drop(bfs6);
|
||||
inner.bound_first_udp.insert(udp_port, None);
|
||||
} else {
|
||||
inner.bound_first_udp.insert(udp_port, Some(bfs4, bfs6));
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
@ -53,7 +65,18 @@ impl Network {
|
||||
}
|
||||
}
|
||||
if let (Some(bfs4), Some(bfs6)) = (bound_first_socket_v4, bound_first_socket_v6) {
|
||||
inner.bound_first_tcp.insert(tcp_port, (bfs4, bfs6));
|
||||
cfg_if! {
|
||||
if #[cfg(windows)] {
|
||||
// On windows, drop the socket. This is a race condition, but there's
|
||||
// no way around it. This isn't for security anyway, it's to prevent multiple copies of the
|
||||
// app from binding on the same port.
|
||||
drop(bfs4);
|
||||
drop(bfs6);
|
||||
inner.bound_first_tcp.insert(tcp_port, None);
|
||||
} else {
|
||||
inner.bound_first_tcp.insert(tcp_port, Some(bfs4, bfs6));
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
|
Loading…
Reference in New Issue
Block a user