@@ -401,7 +401,7 @@ fn send(state: &UdpSocketState, io: SockRef<'_>, transmit: &Transmit<'_>) -> io:
401401 . enumerate ( )
402402 . take ( BATCH_SIZE )
403403 {
404- prepare_msg (
404+ prepare_msg_x (
405405 & Transmit {
406406 destination : transmit. destination ,
407407 ecn : transmit. ecn ,
@@ -437,6 +437,15 @@ fn send(state: &UdpSocketState, io: SockRef<'_>, transmit: &Transmit<'_>) -> io:
437437
438438#[ cfg( any( target_os = "openbsd" , target_os = "netbsd" , apple_slow) ) ]
439439fn send ( state : & UdpSocketState , io : SockRef < ' _ > , transmit : & Transmit < ' _ > ) -> io:: Result < ( ) > {
440+ send_single ( state, io, transmit)
441+ }
442+
443+ #[ cfg( any( target_os = "openbsd" , target_os = "netbsd" , apple) ) ]
444+ fn send_single (
445+ state : & UdpSocketState ,
446+ io : SockRef < ' _ > ,
447+ transmit : & Transmit < ' _ > ,
448+ ) -> io:: Result < ( ) > {
440449 let mut hdr: libc:: msghdr = unsafe { mem:: zeroed ( ) } ;
441450 let mut iov: libc:: iovec = unsafe { mem:: zeroed ( ) } ;
442451 let mut ctrl = cmsg:: Aligned ( [ 0u8 ; CMSG_LEN ] ) ;
@@ -527,7 +536,7 @@ fn recv(io: SockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) ->
527536 let mut hdrs = unsafe { mem:: zeroed :: < [ msghdr_x ; BATCH_SIZE ] > ( ) } ;
528537 let max_msg_count = bufs. len ( ) . min ( BATCH_SIZE ) ;
529538 for i in 0 ..max_msg_count {
530- prepare_recv ( & mut bufs[ i] , & mut names[ i] , & mut ctrls[ i] , & mut hdrs[ i] ) ;
539+ prepare_recv_x ( & mut bufs[ i] , & mut names[ i] , & mut ctrls[ i] , & mut hdrs[ i] ) ;
531540 }
532541 let msg_count = loop {
533542 let n = unsafe { recvmsg_x ( io. as_raw_fd ( ) , hdrs. as_mut_ptr ( ) , max_msg_count as _ , 0 ) } ;
@@ -557,6 +566,21 @@ fn recv(io: SockRef<'_>, bufs: &mut [IoSliceMut<'_>], meta: &mut [RecvMeta]) ->
557566 apple_slow
558567) ) ]
559568fn recv ( io : SockRef < ' _ > , bufs : & mut [ IoSliceMut < ' _ > ] , meta : & mut [ RecvMeta ] ) -> io:: Result < usize > {
569+ recv_single ( io, bufs, meta)
570+ }
571+
572+ #[ cfg( any(
573+ target_os = "openbsd" ,
574+ target_os = "netbsd" ,
575+ target_os = "dragonfly" ,
576+ solarish,
577+ apple
578+ ) ) ]
579+ fn recv_single (
580+ io : SockRef < ' _ > ,
581+ bufs : & mut [ IoSliceMut < ' _ > ] ,
582+ meta : & mut [ RecvMeta ] ,
583+ ) -> io:: Result < usize > {
560584 let mut name = MaybeUninit :: < libc:: sockaddr_storage > :: uninit ( ) ;
561585 let mut ctrl = cmsg:: Aligned ( MaybeUninit :: < [ u8 ; CMSG_LEN ] > :: uninit ( ) ) ;
562586 let mut hdr = unsafe { mem:: zeroed :: < libc:: msghdr > ( ) } ;
@@ -588,8 +612,7 @@ const CMSG_LEN: usize = 88;
588612fn prepare_msg (
589613 transmit : & Transmit < ' _ > ,
590614 dst_addr : & socket2:: SockAddr ,
591- #[ cfg( not( apple_fast) ) ] hdr : & mut libc:: msghdr ,
592- #[ cfg( apple_fast) ] hdr : & mut msghdr_x ,
615+ hdr : & mut libc:: msghdr ,
593616 iov : & mut libc:: iovec ,
594617 ctrl : & mut cmsg:: Aligned < [ u8 ; CMSG_LEN ] > ,
595618 #[ allow( unused_variables) ] // only used on FreeBSD & macOS
@@ -679,7 +702,66 @@ fn prepare_msg(
679702 encoder. finish ( ) ;
680703}
681704
682- #[ cfg( not( apple_fast) ) ]
705+ /// Prepares an `msghdr_x` for use with `sendmsg_x`.
706+ #[ cfg( apple_fast) ]
707+ fn prepare_msg_x (
708+ transmit : & Transmit < ' _ > ,
709+ dst_addr : & socket2:: SockAddr ,
710+ hdr : & mut msghdr_x ,
711+ iov : & mut libc:: iovec ,
712+ ctrl : & mut cmsg:: Aligned < [ u8 ; CMSG_LEN ] > ,
713+ #[ allow( unused_variables) ] encode_src_ip : bool ,
714+ sendmsg_einval : bool ,
715+ ) {
716+ iov. iov_base = transmit. contents . as_ptr ( ) as * const _ as * mut _ ;
717+ iov. iov_len = transmit. contents . len ( ) ;
718+
719+ let name = dst_addr. as_ptr ( ) as * mut libc:: c_void ;
720+ let namelen = dst_addr. len ( ) ;
721+ hdr. msg_name = name as * mut _ ;
722+ hdr. msg_namelen = namelen;
723+ hdr. msg_iov = iov;
724+ hdr. msg_iovlen = 1 ;
725+
726+ hdr. msg_control = ctrl. 0 . as_mut_ptr ( ) as _ ;
727+ hdr. msg_controllen = CMSG_LEN as _ ;
728+ let mut encoder = unsafe { cmsg:: Encoder :: new ( hdr) } ;
729+ let ecn = transmit. ecn . map_or ( 0 , |x| x as libc:: c_int ) ;
730+ let is_ipv4 = transmit. destination . is_ipv4 ( )
731+ || matches ! ( transmit. destination. ip( ) , IpAddr :: V6 ( addr) if addr. to_ipv4_mapped( ) . is_some( ) ) ;
732+ if is_ipv4 {
733+ if !sendmsg_einval {
734+ encoder. push ( libc:: IPPROTO_IP , libc:: IP_TOS , ecn as IpTosTy ) ;
735+ }
736+ } else {
737+ encoder. push ( libc:: IPPROTO_IPV6 , libc:: IPV6_TCLASS , ecn) ;
738+ }
739+
740+ if let Some ( ip) = & transmit. src_ip {
741+ match ip {
742+ IpAddr :: V4 ( v4) => {
743+ if encode_src_ip {
744+ let addr = libc:: in_addr {
745+ s_addr : u32:: from_ne_bytes ( v4. octets ( ) ) ,
746+ } ;
747+ encoder. push ( libc:: IPPROTO_IP , libc:: IP_RECVDSTADDR , addr) ;
748+ }
749+ }
750+ IpAddr :: V6 ( v6) => {
751+ let pktinfo = libc:: in6_pktinfo {
752+ ipi6_ifindex : 0 ,
753+ ipi6_addr : libc:: in6_addr {
754+ s6_addr : v6. octets ( ) ,
755+ } ,
756+ } ;
757+ encoder. push ( libc:: IPPROTO_IPV6 , libc:: IPV6_PKTINFO , pktinfo) ;
758+ }
759+ }
760+ }
761+
762+ encoder. finish ( ) ;
763+ }
764+
683765fn prepare_recv (
684766 buf : & mut IoSliceMut ,
685767 name : & mut MaybeUninit < libc:: sockaddr_storage > ,
@@ -695,8 +777,9 @@ fn prepare_recv(
695777 hdr. msg_flags = 0 ;
696778}
697779
780+ /// Prepares an `msghdr_x` for receiving with `recvmsg_x`.
698781#[ cfg( apple_fast) ]
699- fn prepare_recv (
782+ fn prepare_recv_x (
700783 buf : & mut IoSliceMut ,
701784 name : & mut MaybeUninit < libc:: sockaddr_storage > ,
702785 ctrl : & mut cmsg:: Aligned < [ u8 ; CMSG_LEN ] > ,
0 commit comments