@@ -198,9 +198,25 @@ fn send(io: &mio::net::UdpSocket, transmits: &[Transmit]) -> io::Result<usize> {
198
198
let mut msgs: [ libc:: mmsghdr ; BATCH_SIZE ] = unsafe { mem:: zeroed ( ) } ;
199
199
let mut iovecs: [ libc:: iovec ; BATCH_SIZE ] = unsafe { mem:: zeroed ( ) } ;
200
200
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 ( ) } ;
201
209
for ( i, transmit) in transmits. iter ( ) . enumerate ( ) . take ( BATCH_SIZE ) {
210
+ let dest_addr = unsafe {
211
+ std:: ptr:: write (
212
+ addrs[ i] . as_mut_ptr ( ) ,
213
+ socket2:: SockAddr :: from ( transmit. destination ) ,
214
+ ) ;
215
+ & mut * ( & mut addrs[ i] as * mut _ as * mut _ )
216
+ } ;
202
217
prepare_msg (
203
218
transmit,
219
+ dest_addr,
204
220
& mut msgs[ i] . msg_hdr ,
205
221
& mut iovecs[ i] ,
206
222
& mut cmsgs[ i] ,
@@ -233,7 +249,8 @@ fn send(io: &mio::net::UdpSocket, transmits: &[Transmit]) -> io::Result<usize> {
233
249
let mut ctrl = cmsg:: Aligned ( [ 0u8 ; CMSG_LEN ] ) ;
234
250
let mut sent = 0 ;
235
251
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) ;
237
254
let n = unsafe { libc:: sendmsg ( io. as_raw_fd ( ) , & hdr, 0 ) } ;
238
255
if n == -1 {
239
256
let e = io:: Error :: last_os_error ( ) ;
@@ -334,19 +351,23 @@ const CMSG_LEN: usize = 80;
334
351
335
352
fn prepare_msg (
336
353
transmit : & Transmit ,
354
+ dest_addr : & socket2:: SockAddr ,
337
355
hdr : & mut libc:: msghdr ,
338
356
iov : & mut libc:: iovec ,
339
357
ctrl : & mut cmsg:: Aligned < [ u8 ; CMSG_LEN ] > ,
340
358
) {
341
359
iov. iov_base = transmit. contents . as_ptr ( ) as * const _ as * mut _ ;
342
360
iov. iov_len = transmit. contents . len ( ) ;
343
361
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 = dest_addr. as_ptr ( ) as * mut libc:: c_void ;
368
+ let namelen = dest_addr. len ( ) ;
369
+ hdr. msg_name = name as * mut _ ;
370
+ hdr. msg_namelen = namelen;
350
371
hdr. msg_iov = iov;
351
372
hdr. msg_iovlen = 1 ;
352
373
0 commit comments