Skip to content

Commit

Permalink
g3-socket: support windows SO_REUSE_UNICASTPORT
Browse files Browse the repository at this point in the history
  • Loading branch information
zh-jq-b committed Sep 24, 2024
1 parent 9b29139 commit 8d4843f
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 15 deletions.
4 changes: 1 addition & 3 deletions lib/g3-socket/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ rust-version = "1.80.0"
[dependencies]
tokio = { workspace = true, features = ["net"] }
socket2 = { version = "0.5", features = ["all"] }
libc.workspace = true
fastrand.workspace = true
g3-types.workspace = true

[target.'cfg(unix)'.dependencies]
libc.workspace = true
12 changes: 8 additions & 4 deletions lib/g3-socket/src/bind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

use std::io;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
#[cfg(any(target_os = "linux", target_os = "android"))]
use std::os::unix::io::AsRawFd;

use socket2::{SockAddr, Socket};

Expand All @@ -26,6 +24,8 @@ use g3_types::net::InterfaceName;

#[cfg(any(target_os = "linux", target_os = "android"))]
use super::sockopt::set_bind_address_no_port;
#[cfg(windows)]
use super::sockopt::set_reuse_unicastport;
use crate::util::AddressFamily;

#[derive(Clone, Copy, Debug, Default)]
Expand Down Expand Up @@ -65,13 +65,17 @@ impl BindAddr {
));
}
#[cfg(any(target_os = "linux", target_os = "android"))]
set_bind_address_no_port(socket.as_raw_fd(), true)?;
set_bind_address_no_port(socket, true)?;
#[cfg(windows)]
set_reuse_unicastport(socket, true)?;
let addr: SockAddr = SocketAddr::new(*ip, 0).into();
socket.bind(&addr)
}
#[cfg(any(target_os = "linux", target_os = "android"))]
BindAddr::Interface(name) => {
set_bind_address_no_port(socket.as_raw_fd(), true)?;
set_bind_address_no_port(socket, true)?;
#[cfg(windows)]
set_reuse_unicastport(socket, true)?;
socket.bind_device(Some(name.as_bytes()))
}
}
Expand Down
1 change: 0 additions & 1 deletion lib/g3-socket/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
* limitations under the License.
*/

#[cfg(any(target_os = "linux", target_os = "android"))]
mod sockopt;

mod raw;
Expand Down
25 changes: 25 additions & 0 deletions lib/g3-socket/src/sockopt/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2024 ByteDance and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#[cfg(any(target_os = "linux", target_os = "android"))]
mod unix;
#[cfg(any(target_os = "linux", target_os = "android"))]
pub(crate) use unix::set_bind_address_no_port;

#[cfg(windows)]
mod windows;
#[cfg(windows)]
pub(crate) use windows::set_reuse_unicastport;
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2023 ByteDance and/or its affiliates.
* Copyright 2024 ByteDance and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,25 +15,26 @@
*/

use std::io;
use std::os::unix::io::AsRawFd;

use libc::{c_int, c_void};
use libc::{c_int, c_void, socklen_t};

unsafe fn setsockopt<T>(fd: c_int, opt: c_int, val: c_int, payload: T) -> io::Result<()>
unsafe fn setsockopt<T>(fd: c_int, level: c_int, name: c_int, value: T) -> io::Result<()>
where
T: Copy,
{
let payload = &payload as *const T as *const c_void;
let ret = libc::setsockopt(fd, opt, val, payload, size_of::<T>() as libc::socklen_t);
let payload = &value as *const T as *const c_void;
let ret = libc::setsockopt(fd, level, name, payload, size_of::<T>() as socklen_t);
if ret == -1 {
return Err(io::Error::last_os_error());
}
Ok(())
}

pub(crate) fn set_bind_address_no_port(fd: c_int, enable: bool) -> io::Result<()> {
pub(crate) fn set_bind_address_no_port<T: AsRawFd>(fd: &T, enable: bool) -> io::Result<()> {
unsafe {
setsockopt(
fd,
fd.as_raw_fd(),
libc::IPPROTO_IP,
libc::IP_BIND_ADDRESS_NO_PORT,
enable as c_int,
Expand Down
50 changes: 50 additions & 0 deletions lib/g3-socket/src/sockopt/windows.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright 2024 ByteDance and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

use std::io;
use std::os::windows::io::AsRawSocket;

use libc::{c_char, c_int, SOCKET};

// windows_sys::Win32::Networking::WinSock::SOL_SOCKET
const SOL_SOCKET: i32 = 65535i32;

// windows_sys::Win32::Networking::WinSock::SO_REUSE_UNICASTPORT
const SO_REUSE_UNICASTPORT: i32 = 12295i32;

unsafe fn setsockopt<T>(socket: SOCKET, level: c_int, name: c_int, value: T) -> io::Result<()>
where
T: Copy,
{
let payload = &value as *const T as *const c_char;
let ret = libc::setsockopt(socket, level, name, payload, size_of::<T>() as c_int);
if ret == -1 {
return Err(io::Error::last_os_error());
}
Ok(())
}

pub(crate) fn set_reuse_unicastport<T: AsRawSocket>(socket: &T, enable: bool) -> io::Result<()> {
unsafe {
setsockopt(
socket.as_raw_socket(),
SOL_SOCKET,
SO_REUSE_UNICASTPORT,
enable as c_int,
)?;
Ok(())
}
}

0 comments on commit 8d4843f

Please sign in to comment.