From 9750195caa1a3f6f93883f55ef8a1a0098c1bd18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 30 Nov 2018 19:38:25 +0200 Subject: [PATCH] ts-udpsrc: Dup the socket so that both tokio and GIO can take ownership of it Otherwise both would be closing the same socket, which a) breaks the second user of the socket if any and b) could on the second close cause a completely unrelated socket to be closed. Windows part of the code is untested. --- gst-plugin-threadshare/Cargo.toml | 4 +++ gst-plugin-threadshare/src/lib.rs | 5 ++++ gst-plugin-threadshare/src/udpsrc.rs | 44 ++++++++++++++++++++++++---- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/gst-plugin-threadshare/Cargo.toml b/gst-plugin-threadshare/Cargo.toml index 425c7c34..961ac0f6 100644 --- a/gst-plugin-threadshare/Cargo.toml +++ b/gst-plugin-threadshare/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Sebastian Dröge "] license = "LGPL-2.1+" [dependencies] +libc = "0.2" glib-sys = { git = "https://github.com/gtk-rs/sys" } gobject-sys = { git = "https://github.com/gtk-rs/sys" } gio-sys = { git = "https://github.com/gtk-rs/sys" } @@ -26,6 +27,9 @@ either = "1.0" rand = "0.5" net2 = "0.2" +[target.'cfg(windows)'.dependencies] +winapi = { version = "0.3", features = ["winsock2", "processthreadsapi"] } + [lib] name = "gstthreadshare" crate-type = ["cdylib", "rlib"] diff --git a/gst-plugin-threadshare/src/lib.rs b/gst-plugin-threadshare/src/lib.rs index c6d5f6ed..65f8fd30 100644 --- a/gst-plugin-threadshare/src/lib.rs +++ b/gst-plugin-threadshare/src/lib.rs @@ -17,6 +17,8 @@ #![crate_type = "cdylib"] +extern crate libc; + extern crate gio_sys as gio_ffi; extern crate glib_sys as glib_ffi; extern crate gobject_sys as gobject_ffi; @@ -47,6 +49,9 @@ extern crate lazy_static; extern crate net2; +#[cfg(windows)] +extern crate winapi; + mod iocontext; mod socket; diff --git a/gst-plugin-threadshare/src/udpsrc.rs b/gst-plugin-threadshare/src/udpsrc.rs index eda24f56..8558cd7c 100644 --- a/gst-plugin-threadshare/src/udpsrc.rs +++ b/gst-plugin-threadshare/src/udpsrc.rs @@ -95,12 +95,16 @@ impl GioSocketWrapper { #[cfg(unix)] fn get(&self) -> T { - unsafe { FromRawFd::from_raw_fd(gio_ffi::g_socket_get_fd(self.socket)) } + use libc; + + unsafe { FromRawFd::from_raw_fd(libc::dup(gio_ffi::g_socket_get_fd(self.socket))) } } #[cfg(windows)] fn get(&self) -> T { - unsafe { FromRawSocket::from_raw_socket(ffi::g_socket_get_fd(self.socket) as _) } + unsafe { + FromRawSocket::from_raw_socket(dup_socket(ffi::g_socket_get_fd(self.socket) as _) as _) + } } } @@ -120,6 +124,32 @@ impl Drop for GioSocketWrapper { } } +#[cfg(windows)] +unsafe fn dup_socket(socket: usize) -> usize { + use std::mem; + use winapi::shared::minwindef::DWORD; + use winapi::shared::ws2def; + use winapi::um::processthreadsapi; + use winapi::um::winsock2; + use winapi::um::winsock2; + + let mut proto_info = mem::zeroed(); + let ret = winsock2::WSADuplicateSocketA( + socket, + processthreadsapi::GetCurrentProcess(), + &mut proto_info, + ); + assert_eq!(ret, 0); + winsock2::WSASocketA( + ws2def::AF_INET, + ws2def::SOCK_DGRAM, + ws2def::IPPROTO_UDP, + &mut proto_info, + 0, + 0, + ); +} + #[derive(Debug, Clone)] struct Settings { address: Option, @@ -223,8 +253,8 @@ pub struct UdpReader { } impl UdpReader { - pub fn new(socket: net::UdpSocket) -> Self { - Self { socket: socket } + fn new(socket: net::UdpSocket) -> Self { + Self { socket } } } @@ -668,7 +698,9 @@ impl UdpSrc { // Store the socket as used-socket in the settings #[cfg(unix)] { - let fd = socket.as_raw_fd(); + use libc; + + let fd = unsafe { libc::dup(socket.as_raw_fd()) }; // This is technically unsafe because it allows // us to share the fd between the socket and the @@ -694,7 +726,7 @@ impl UdpSrc { } #[cfg(windows)] { - let fd = socket.as_raw_socket(); + let fd = unsafe { dup_socket(socket.as_raw_socket() as _) as _ }; // This is technically unsafe because it allows // us to share the fd between the socket and the