Skip to content

Commit 22fa3a4

Browse files
committed
Refactor Socket::send_to_vectored
1 parent 609083d commit 22fa3a4

File tree

5 files changed

+81
-70
lines changed

5 files changed

+81
-70
lines changed

src/sockaddr.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ impl SockAddr {
5959
&self.storage as *const _ as *const _
6060
}
6161

62+
/// Returns a raw pointer to the address storage.
63+
#[cfg(unix)]
64+
pub(crate) fn as_storage_ptr(&self) -> *const sockaddr_storage {
65+
&self.storage
66+
}
67+
6268
/// Returns this address as a `SocketAddr` if it is in the `AF_INET` (IP v4)
6369
/// or `AF_INET6` (IP v6) family, otherwise returns `None`.
6470
pub fn as_std(&self) -> Option<SocketAddr> {

src/socket.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -465,21 +465,27 @@ impl Socket {
465465
sys::send_to(self.inner, buf, addr, flags)
466466
}
467467

468-
/// Identical to [`send_with_flags`] but writes from a slice of buffers.
468+
/// Send data to a peer listening on `addr`. Returns the amount of bytes
469+
/// written.
470+
#[cfg(not(target_os = "redox"))]
471+
pub fn send_to_vectored(&self, bufs: &[IoSlice<'_>], addr: &SockAddr) -> io::Result<usize> {
472+
self.send_to_vectored_with_flags(bufs, addr, 0)
473+
}
474+
475+
/// Identical to [`send_to_vectored`] but allows for specification of
476+
/// arbitrary flags to the underlying `sendmsg`/`WSASendTo` call.
469477
///
470-
/// [`send_with_flags`]: #method.send_with_flags
478+
/// [`send_to_vectored`]: Socket::send_to_vectored
471479
#[cfg(not(target_os = "redox"))]
472-
pub fn send_to_vectored(
480+
pub fn send_to_vectored_with_flags(
473481
&self,
474482
bufs: &[IoSlice<'_>],
475483
addr: &SockAddr,
476484
flags: i32,
477485
) -> io::Result<usize> {
478-
self.inner().send_to_vectored(bufs, flags, addr)
486+
sys::send_to_vectored(self.inner, bufs, addr, flags)
479487
}
480488

481-
// ================================================
482-
483489
/// Gets the value of the `IP_TTL` option for this socket.
484490
///
485491
/// For more information about this option, see [`set_ttl`][link].

src/sys/unix.rs

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -493,20 +493,7 @@ pub(crate) fn send_vectored(
493493
bufs: &[IoSlice<'_>],
494494
flags: c_int,
495495
) -> io::Result<usize> {
496-
let mut msg = libc::msghdr {
497-
msg_name: ptr::null_mut(),
498-
msg_namelen: 0,
499-
// Safety: we're creating a `*mut` pointer from a reference, which is UB
500-
// once actually used. However the OS should not write to it in the
501-
// `sendmsg` system call.
502-
msg_iov: bufs.as_ptr() as *mut _,
503-
msg_iovlen: min(bufs.len(), IovLen::MAX as usize) as IovLen,
504-
msg_control: ptr::null_mut(),
505-
msg_controllen: 0,
506-
msg_flags: 0,
507-
};
508-
509-
syscall!(sendmsg(fd, &mut msg, flags)).map(|n| n as usize)
496+
sendmsg(fd, ptr::null(), 0, bufs, flags)
510497
}
511498

512499
pub(crate) fn send_to(
@@ -526,6 +513,40 @@ pub(crate) fn send_to(
526513
.map(|n| n as usize)
527514
}
528515

516+
#[cfg(not(target_os = "redox"))]
517+
pub(crate) fn send_to_vectored(
518+
fd: SysSocket,
519+
bufs: &[IoSlice<'_>],
520+
addr: &SockAddr,
521+
flags: c_int,
522+
) -> io::Result<usize> {
523+
sendmsg(fd, addr.as_storage_ptr(), addr.len(), bufs, flags)
524+
}
525+
526+
/// Returns the (bytes received, sending address len, `RecvFlags`).
527+
fn sendmsg(
528+
fd: SysSocket,
529+
msg_name: *const sockaddr_storage,
530+
msg_namelen: socklen_t,
531+
bufs: &[IoSlice<'_>],
532+
flags: c_int,
533+
) -> io::Result<usize> {
534+
let mut msg = libc::msghdr {
535+
// Safety: we're creating a `*mut` pointer from a reference, which is UB
536+
// once actually used. However the OS should not write to it in the
537+
// `sendmsg` system call.
538+
msg_name: (msg_name as *mut sockaddr_storage).cast(),
539+
msg_namelen,
540+
// Safety: Same as above about `*const` -> `*mut`.
541+
msg_iov: bufs.as_ptr() as *mut _,
542+
msg_iovlen: min(bufs.len(), IovLen::MAX as usize) as IovLen,
543+
msg_control: ptr::null_mut(),
544+
msg_controllen: 0,
545+
msg_flags: 0,
546+
};
547+
syscall!(sendmsg(fd, &mut msg, flags)).map(|n| n as usize)
548+
}
549+
529550
/// Unix only API.
530551
impl crate::Socket {
531552
/// Accept a new incoming connection from this listener.
@@ -661,27 +682,6 @@ pub struct Socket {
661682
}
662683

663684
impl Socket {
664-
#[cfg(not(target_os = "redox"))]
665-
pub fn send_to_vectored(
666-
&self,
667-
bufs: &[IoSlice<'_>],
668-
flags: c_int,
669-
addr: &SockAddr,
670-
) -> io::Result<usize> {
671-
let mut msg = libc::msghdr {
672-
msg_name: addr.as_ptr() as *mut c_void,
673-
msg_namelen: addr.len(),
674-
msg_iov: bufs.as_ptr() as *mut libc::iovec,
675-
msg_iovlen: bufs.len().min(IovLen::MAX as usize) as IovLen,
676-
msg_control: std::ptr::null_mut(),
677-
msg_controllen: 0,
678-
msg_flags: 0,
679-
};
680-
681-
let n = syscall!(sendmsg(self.fd, &mut msg as *mut libc::msghdr, flags))?;
682-
Ok(n as usize)
683-
}
684-
685685
pub fn ttl(&self) -> io::Result<u32> {
686686
unsafe {
687687
let raw: c_int = self.getsockopt(libc::IPPROTO_IP, libc::IP_TTL)?;

src/sys/windows.rs

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,8 @@ pub(crate) fn send_vectored(
437437
//
438438
// Tracking issue: https://github.com/rust-lang/socket2-rs/issues/129.
439439
//
440+
// NOTE: `send_to_vectored` has the same problem.
441+
//
440442
// [1] https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasend
441443
bufs.as_ptr() as *mut _,
442444
min(bufs.len(), DWORD::max_value() as usize) as DWORD,
@@ -472,6 +474,32 @@ pub(crate) fn send_to(
472474
.map(|n| n as usize)
473475
}
474476

477+
pub(crate) fn send_to_vectored(
478+
socket: SysSocket,
479+
bufs: &[IoSlice<'_>],
480+
addr: &SockAddr,
481+
flags: c_int,
482+
) -> io::Result<usize> {
483+
let mut nsent = 0;
484+
syscall!(
485+
WSASendTo(
486+
socket,
487+
// FIXME: Same problem as in `send_vectored`.
488+
bufs.as_ptr() as *mut _,
489+
bufs.len().min(DWORD::MAX as usize) as DWORD,
490+
&mut nsent,
491+
flags as DWORD,
492+
addr.as_ptr(),
493+
addr.len(),
494+
ptr::null_mut(),
495+
None,
496+
),
497+
PartialEq::eq,
498+
sock::SOCKET_ERROR
499+
)
500+
.map(|_| nsent as usize)
501+
}
502+
475503
/// Caller must ensure `T` is the correct type for `opt` and `val`.
476504
unsafe fn getsockopt<T>(socket: SysSocket, opt: c_int, val: c_int) -> io::Result<T> {
477505
let mut payload: MaybeUninit<T> = MaybeUninit::uninit();
@@ -525,34 +553,6 @@ pub struct Socket {
525553
}
526554

527555
impl Socket {
528-
pub fn send_to_vectored(
529-
&self,
530-
bufs: &[IoSlice<'_>],
531-
flags: c_int,
532-
addr: &SockAddr,
533-
) -> io::Result<usize> {
534-
let mut nsent = 0;
535-
let ret = unsafe {
536-
sock::WSASendTo(
537-
self.socket,
538-
bufs.as_ptr() as *mut WSABUF,
539-
bufs.len().min(DWORD::MAX as usize) as DWORD,
540-
&mut nsent,
541-
flags as DWORD,
542-
addr.as_ptr(),
543-
addr.len(),
544-
std::ptr::null_mut(),
545-
None,
546-
)
547-
};
548-
match ret {
549-
0 => Ok(nsent as usize),
550-
_ => Err(last_error()),
551-
}
552-
}
553-
554-
// ================================================
555-
556556
pub fn ttl(&self) -> io::Result<u32> {
557557
unsafe {
558558
let raw: c_int = self.getsockopt(IPPROTO_IP, IP_TTL)?;

src/tests.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ fn send_from_recv_to_vectored() {
215215
IoSlice::new(b"menswear"),
216216
],
217217
&addr_b,
218-
0,
219218
)
220219
.unwrap();
221220
assert_eq!(sent, 18);

0 commit comments

Comments
 (0)