Skip to main content

unbounded_udp/
lib.rs

1// Copyright (c) 2022, Yuri6037
2//
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without modification,
6// are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of Yuri6037 nor the names of its contributors
14// may be used to endorse or promote products derived from this software
15// without specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29use std::net::UdpSocket;
30use std::io::Result;
31use std::io::Error;
32
33pub enum Domain {
34    IpV4,
35    Ipv6
36}
37
38mod sealing {
39    pub trait Unbounded {}
40
41    impl Unbounded for std::net::UdpSocket {}
42}
43
44pub trait Unbounded : sealing::Unbounded where Self: Sized {
45    fn unbounded(domain: Domain) -> Result<Self>;
46}
47
48impl Unbounded for UdpSocket {
49    fn unbounded(domain: Domain) -> Result<Self> {
50        #[cfg(unix)]
51        {
52            use std::os::unix::io::FromRawFd;
53            let domain = match domain {
54                Domain::IpV4 => libc::AF_INET,
55                Domain::Ipv6 => libc::AF_INET6
56            };
57            let fd = unsafe { libc::socket(domain, libc::SOCK_DGRAM, libc::IPPROTO_UDP) };
58            if fd == -1 {
59                return Err(Error::last_os_error());
60            }
61            let socket = unsafe { UdpSocket::from_raw_fd(fd) };
62            Ok(socket)
63        }
64        #[cfg(windows)]
65        {
66            use std::os::windows::io::FromRawSocket;
67            use std::os::windows::io::RawSocket;
68            use windows_sys::Win32::Networking::WinSock::SOCK_DGRAM;
69            use windows_sys::Win32::Networking::WinSock::IPPROTO_UDP;
70            use windows_sys::Win32::Networking::WinSock::AF_INET;
71            use windows_sys::Win32::Networking::WinSock::AF_INET6;
72            use windows_sys::Win32::Networking::WinSock::socket;
73            use windows_sys::Win32::Networking::WinSock::WSAGetLastError;
74            use windows_sys::Win32::Networking::WinSock::INVALID_SOCKET;
75            let domain = match domain {
76                Domain::IpV4 => AF_INET,
77                Domain::Ipv6 => AF_INET6
78            };
79            let sock = unsafe { socket(domain as i32, SOCK_DGRAM as i32, IPPROTO_UDP) };
80            if sock == INVALID_SOCKET {
81                return Err(Error::from_raw_os_error(unsafe { WSAGetLastError() }));
82            }
83            let socket = unsafe { UdpSocket::from_raw_socket(sock as RawSocket) };
84            Ok(socket)
85        }
86    }
87}