@@ -198,9 +198,25 @@ fn send(io: &mio::net::UdpSocket, transmits: &[Transmit]) -> io::Result<usize> {
198198 let mut msgs: [ libc:: mmsghdr ; BATCH_SIZE ] = unsafe { mem:: zeroed ( ) } ;
199199 let mut iovecs: [ libc:: iovec ; BATCH_SIZE ] = unsafe { mem:: zeroed ( ) } ;
200200 let mut cmsgs = [ cmsg:: Aligned ( [ 0u8 ; CMSG_LEN ] ) ; BATCH_SIZE ] ;
201+ // This assume_init looks a bit weird because one might think it
202+ // assumes the SockAddr data to be initialized, but that call
203+ // refers to the whole array, which itself is made up of MaybeUninit
204+ // containers. Their presence protects the SockAddr inside from
205+ // being assumed as initialized by the assume_init call.
206+ // TODO: Replace this with uninit_array once it becomes MSRV-stable
207+ let mut addrs: [ MaybeUninit < socket2:: SockAddr > ; BATCH_SIZE ] =
208+ unsafe { MaybeUninit :: uninit ( ) . assume_init ( ) } ;
201209 for ( i, transmit) in transmits. iter ( ) . enumerate ( ) . take ( BATCH_SIZE ) {
210+ let dst_addr = unsafe {
211+ std:: ptr:: write (
212+ addrs[ i] . as_mut_ptr ( ) ,
213+ socket2:: SockAddr :: from ( transmit. destination ) ,
214+ ) ;
215+ & * addrs[ i] . as_ptr ( )
216+ } ;
202217 prepare_msg (
203218 transmit,
219+ dst_addr,
204220 & mut msgs[ i] . msg_hdr ,
205221 & mut iovecs[ i] ,
206222 & mut cmsgs[ i] ,
@@ -233,7 +249,8 @@ fn send(io: &mio::net::UdpSocket, transmits: &[Transmit]) -> io::Result<usize> {
233249 let mut ctrl = cmsg:: Aligned ( [ 0u8 ; CMSG_LEN ] ) ;
234250 let mut sent = 0 ;
235251 while sent < transmits. len ( ) {
236- prepare_msg ( & transmits[ sent] , & mut hdr, & mut iov, & mut ctrl) ;
252+ let addr = socket2:: SockAddr :: from ( transmits[ sent] . destination ) ;
253+ prepare_msg ( & transmits[ sent] , & addr, & mut hdr, & mut iov, & mut ctrl) ;
237254 let n = unsafe { libc:: sendmsg ( io. as_raw_fd ( ) , & hdr, 0 ) } ;
238255 if n == -1 {
239256 let e = io:: Error :: last_os_error ( ) ;
@@ -334,19 +351,23 @@ const CMSG_LEN: usize = 80;
334351
335352fn prepare_msg (
336353 transmit : & Transmit ,
354+ dst_addr : & socket2:: SockAddr ,
337355 hdr : & mut libc:: msghdr ,
338356 iov : & mut libc:: iovec ,
339357 ctrl : & mut cmsg:: Aligned < [ u8 ; CMSG_LEN ] > ,
340358) {
341359 iov. iov_base = transmit. contents . as_ptr ( ) as * const _ as * mut _ ;
342360 iov. iov_len = transmit. contents . len ( ) ;
343361
344- let ( name, namelen) = match transmit. destination {
345- SocketAddr :: V4 ( ref addr) => ( addr as * const _ as _ , mem:: size_of :: < libc:: sockaddr_in > ( ) ) ,
346- SocketAddr :: V6 ( ref addr) => ( addr as * const _ as _ , mem:: size_of :: < libc:: sockaddr_in6 > ( ) ) ,
347- } ;
348- hdr. msg_name = name;
349- hdr. msg_namelen = namelen as _ ;
362+ // SAFETY: Casting the pointer to a mutable one is legal,
363+ // as sendmsg is guaranteed to not alter the mutable pointer
364+ // as per the POSIX spec. See the section on the sys/socket.h
365+ // header for details. The type is only mutable in the first
366+ // place because it is reused by recvmsg as well.
367+ let name = dst_addr. as_ptr ( ) as * mut libc:: c_void ;
368+ let namelen = dst_addr. len ( ) ;
369+ hdr. msg_name = name as * mut _ ;
370+ hdr. msg_namelen = namelen;
350371 hdr. msg_iov = iov;
351372 hdr. msg_iovlen = 1 ;
352373
0 commit comments