Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows: WARN:smartdns::server::udp:36: error receiving message on udp_socket (and fix) #391

Closed
chmichael opened this issue Sep 25, 2024 · 6 comments · Fixed by #392
Closed

Comments

@chmichael
Copy link

chmichael commented Sep 25, 2024

Only in windows it throws and UDP warning:
WARN:smartdns::server::udp:36: error receiving message on udp_socket: An existing connection was forcibly closed by the remote host. (os error 10054)

Here's the solution for windows only in rust:
shadowsocks/shadowsocks-rust#262 (comment)
You'll need to import the winapi package too: https://crates.io/crates/winapi

from notes:
Ignoring UdpSocket's WSAECONNRESET error
This is because UdpSocket::recv_from may return WSAECONNRESET
if you called UdpSocket::send_to a destination that is not existed (may be closed).
It is not an error. Could be ignored completely.
We have to ignore it here because it will crash the server.

I hope you add it soon
discussion: #368

@chmichael chmichael changed the title WARN:smartdns::server::udp:36: error receiving message on udp_socket (and fix) Windows: WARN:smartdns::server::udp:36: error receiving message on udp_socket (and fix) Sep 25, 2024
@mokeyish
Copy link
Owner

Thanks, Looks good, I'll check it out this weekend.

There is already a ready-made code, you can just adjust it and give it a try.

The corresponding code is here:

pub fn udp(
sock_addr: SocketAddr,
bind_device: Option<&str>,
bind_type: &str,
) -> io::Result<UdpSocket> {
let device_note = bind_device
.map(|device| format!("@{device}"))
.unwrap_or_default();
log::debug!("binding {} to {:?}{}", bind_type, sock_addr, device_note);
let udp_socket = std::net::UdpSocket::bind(sock_addr)?;
{
let sock_ref = socket2::SockRef::from(&udp_socket);
sock_ref.set_nonblocking(true)?;
sock_ref.set_reuse_address(true)?;
#[cfg(target_os = "macos")]
sock_ref.set_reuse_port(true)?;
#[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]

@mokeyish
Copy link
Owner

I solved this problem a long time ago. At that time, the program crashed. I just changed the error to a warning so that it would not affect the use.

hickory-dns/hickory-dns#1913 (comment)

@chmichael
Copy link
Author

chmichael commented Sep 25, 2024

Done and compiled! No more UDP errors in Windows!

btw it needs the "unsafe declaration" cause of "WSAIoctl".
Maybe you can find somewhere else safe ?

CARGO.TOML add:
[target.'cfg(windows)'.dependencies]
...
// add code below
winapi = { version = "0.3.9", features = ["mswsock", "winsock2"] }
...

MOD.RS:

    pub fn udp(
        sock_addr: SocketAddr,
        bind_device: Option<&str>,
        bind_type: &str,
    ) -> io::Result<UdpSocket> {

        // add code below
        use std::{mem, os::windows::io::AsRawSocket, ptr};
        use winapi::{
            shared::minwindef::{BOOL, DWORD, FALSE, LPDWORD, LPVOID},
            um::{
                mswsock::SIO_UDP_CONNRESET,
                winsock2::{WSAGetLastError, WSAIoctl, SOCKET, SOCKET_ERROR},
                },
        };
       
        ...        
        let udp_socket = std::net::UdpSocket::bind(sock_addr)?;`

        // add code below
        let handle = udp_socket.as_raw_socket() as SOCKET;
        let mut bytes_returned: DWORD = 0;
        let mut enable: BOOL = FALSE;
	    unsafe { 
		    let ret = WSAIoctl(
              handle,
              SIO_UDP_CONNRESET,
              &mut enable as *mut _ as LPVOID,
              mem::size_of_val(&enable) as DWORD,
              ptr::null_mut(),
              0,
              &mut bytes_returned as *mut _ as LPDWORD,
              ptr::null_mut(),
              None,
            );

  	        if ret == SOCKET_ERROR {
               use std::io::Error;

              // Error occurs
              let err_code = WSAGetLastError();
              return Err(Error::from_raw_os_error(err_code));
            }
		};

ps: i did update all the cargo packages to the latest versions and only rustls has a breaking change.

@mokeyish
Copy link
Owner

Calling Windows API, unsafe seems to be inevitable.

But I prefer to use
https://crates.io/crates/windows
instead of winapi, which has not been updated for a long time.

@chmichael
Copy link
Author

Windows GNU build produces UDP 38 error

@mokeyish
Copy link
Owner

Indeed, GNU has not solved this problem. I don't have time to find a solution, and if it is solved, it will only reduce the log warning, which does not affect the use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants