@@ -707,17 +707,42 @@ fn decode_recv<M: cmsg::MsgHdr<ControlMessage = libc::cmsghdr>>(
707707 len : usize ,
708708) -> io:: Result < RecvMeta > {
709709 let name = unsafe { name. assume_init ( ) } ;
710- let mut ecn_bits = 0 ;
711- let mut dst_ip = None ;
712- let mut interface_index = None ;
713- #[ allow( unused_mut) ] // only mutable on Linux
714- let mut stride = len;
710+ let mut ctrl = ControlMetadata {
711+ ecn_bits : 0 ,
712+ dst_ip : None ,
713+ interface_index : None ,
714+ stride : len,
715+ } ;
715716
716717 let cmsg_iter = unsafe { cmsg:: Iter :: new ( hdr) } ;
717718 for cmsg in cmsg_iter {
719+ ctrl. decode ( cmsg) ;
720+ }
721+
722+ Ok ( RecvMeta {
723+ len,
724+ stride : ctrl. stride ,
725+ addr : decode_socket_addr ( & name) ?,
726+ ecn : EcnCodepoint :: from_bits ( ctrl. ecn_bits ) ,
727+ dst_ip : ctrl. dst_ip ,
728+ interface_index : ctrl. interface_index ,
729+ } )
730+ }
731+
732+ /// Metadata decoded from control messages
733+ struct ControlMetadata {
734+ ecn_bits : u8 ,
735+ dst_ip : Option < IpAddr > ,
736+ interface_index : Option < u32 > ,
737+ stride : usize ,
738+ }
739+
740+ impl ControlMetadata {
741+ /// Decodes a control message and updates the metadata state
742+ fn decode ( & mut self , cmsg : & libc:: cmsghdr ) {
718743 match ( cmsg. cmsg_level , cmsg. cmsg_type ) {
719744 ( libc:: IPPROTO_IP , libc:: IP_TOS ) => unsafe {
720- ecn_bits = cmsg:: decode :: < u8 , libc:: cmsghdr > ( cmsg) ;
745+ self . ecn_bits = cmsg:: decode :: < u8 , libc:: cmsghdr > ( cmsg) ;
721746 } ,
722747 // FreeBSD uses IP_RECVTOS here, and we can be liberal because cmsgs are opt-in.
723748 #[ cfg( not( any(
@@ -727,7 +752,7 @@ fn decode_recv<M: cmsg::MsgHdr<ControlMessage = libc::cmsghdr>>(
727752 solarish
728753 ) ) ) ]
729754 ( libc:: IPPROTO_IP , libc:: IP_RECVTOS ) => unsafe {
730- ecn_bits = cmsg:: decode :: < u8 , libc:: cmsghdr > ( cmsg) ;
755+ self . ecn_bits = cmsg:: decode :: < u8 , libc:: cmsghdr > ( cmsg) ;
731756 } ,
732757 ( libc:: IPPROTO_IPV6 , libc:: IPV6_TCLASS ) => unsafe {
733758 // Temporary hack around broken macos ABI. Remove once upstream fixes it.
@@ -736,45 +761,36 @@ fn decode_recv<M: cmsg::MsgHdr<ControlMessage = libc::cmsghdr>>(
736761 if cfg ! ( apple)
737762 && cmsg. cmsg_len as usize == libc:: CMSG_LEN ( mem:: size_of :: < u8 > ( ) as _ ) as usize
738763 {
739- ecn_bits = cmsg:: decode :: < u8 , libc:: cmsghdr > ( cmsg) ;
764+ self . ecn_bits = cmsg:: decode :: < u8 , libc:: cmsghdr > ( cmsg) ;
740765 } else {
741- ecn_bits = cmsg:: decode :: < libc:: c_int , libc:: cmsghdr > ( cmsg) as u8 ;
766+ self . ecn_bits = cmsg:: decode :: < libc:: c_int , libc:: cmsghdr > ( cmsg) as u8 ;
742767 }
743768 } ,
744769 #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
745770 ( libc:: IPPROTO_IP , libc:: IP_PKTINFO ) => {
746771 let pktinfo = unsafe { cmsg:: decode :: < libc:: in_pktinfo , libc:: cmsghdr > ( cmsg) } ;
747- dst_ip = Some ( IpAddr :: V4 ( Ipv4Addr :: from (
772+ self . dst_ip = Some ( IpAddr :: V4 ( Ipv4Addr :: from (
748773 pktinfo. ipi_addr . s_addr . to_ne_bytes ( ) ,
749774 ) ) ) ;
750- interface_index = Some ( pktinfo. ipi_ifindex as u32 ) ;
775+ self . interface_index = Some ( pktinfo. ipi_ifindex as u32 ) ;
751776 }
752777 #[ cfg( any( bsd, apple) ) ]
753778 ( libc:: IPPROTO_IP , libc:: IP_RECVDSTADDR ) => {
754779 let in_addr = unsafe { cmsg:: decode :: < libc:: in_addr , libc:: cmsghdr > ( cmsg) } ;
755- dst_ip = Some ( IpAddr :: V4 ( Ipv4Addr :: from ( in_addr. s_addr . to_ne_bytes ( ) ) ) ) ;
780+ self . dst_ip = Some ( IpAddr :: V4 ( Ipv4Addr :: from ( in_addr. s_addr . to_ne_bytes ( ) ) ) ) ;
756781 }
757782 ( libc:: IPPROTO_IPV6 , libc:: IPV6_PKTINFO ) => {
758783 let pktinfo = unsafe { cmsg:: decode :: < libc:: in6_pktinfo , libc:: cmsghdr > ( cmsg) } ;
759- dst_ip = Some ( IpAddr :: V6 ( Ipv6Addr :: from ( pktinfo. ipi6_addr . s6_addr ) ) ) ;
760- interface_index = Some ( pktinfo. ipi6_ifindex as u32 ) ;
784+ self . dst_ip = Some ( IpAddr :: V6 ( Ipv6Addr :: from ( pktinfo. ipi6_addr . s6_addr ) ) ) ;
785+ self . interface_index = Some ( pktinfo. ipi6_ifindex as u32 ) ;
761786 }
762787 #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
763788 ( libc:: SOL_UDP , libc:: UDP_GRO ) => unsafe {
764- stride = cmsg:: decode :: < libc:: c_int , libc:: cmsghdr > ( cmsg) as usize ;
789+ self . stride = cmsg:: decode :: < libc:: c_int , libc:: cmsghdr > ( cmsg) as usize ;
765790 } ,
766791 _ => { }
767792 }
768793 }
769-
770- Ok ( RecvMeta {
771- len,
772- stride,
773- addr : decode_socket_addr ( & name) ?,
774- ecn : EcnCodepoint :: from_bits ( ecn_bits) ,
775- dst_ip,
776- interface_index,
777- } )
778794}
779795
780796/// Decodes a `sockaddr_storage` into a `SocketAddr`
0 commit comments