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}