@@ -29,7 +29,11 @@ use std::ptr;
2929use std:: slice;
3030use std:: sync:: atomic;
3131
32+ use std:: net:: Ipv4Addr ;
33+ use std:: net:: Ipv6Addr ;
3234use std:: net:: SocketAddr ;
35+ use std:: net:: SocketAddrV4 ;
36+ use std:: net:: SocketAddrV6 ;
3337
3438#[ cfg( unix) ]
3539use std:: os:: unix:: io:: FromRawFd ;
@@ -42,6 +46,31 @@ use libc::sockaddr;
4246use libc:: ssize_t;
4347use libc:: timespec;
4448
49+ #[ cfg( not( windows) ) ]
50+ use libc:: AF_INET ;
51+ #[ cfg( windows) ]
52+ use winapi:: shared:: ws2def:: AF_INET ;
53+
54+ #[ cfg( not( windows) ) ]
55+ use libc:: AF_INET6 ;
56+ #[ cfg( windows) ]
57+ use winapi:: shared:: ws2def:: AF_INET6 ;
58+
59+ #[ cfg( not( windows) ) ]
60+ use libc:: in_addr;
61+ #[ cfg( windows) ]
62+ use winapi:: shared:: inaddr:: IN_ADDR as in_addr;
63+
64+ #[ cfg( not( windows) ) ]
65+ use libc:: in6_addr;
66+ #[ cfg( windows) ]
67+ use winapi:: shared:: in6addr:: IN6_ADDR as in6_addr;
68+
69+ #[ cfg( not( windows) ) ]
70+ use libc:: sa_family_t;
71+ #[ cfg( windows) ]
72+ use winapi:: shared:: ws2def:: ADDRESS_FAMILY as sa_family_t;
73+
4574#[ cfg( not( windows) ) ]
4675use libc:: sockaddr_in;
4776#[ cfg( windows) ]
@@ -62,15 +91,12 @@ use libc::c_int as socklen_t;
6291#[ cfg( not( windows) ) ]
6392use libc:: socklen_t;
6493
65- #[ cfg( not( windows) ) ]
66- use libc:: AF_INET ;
6794#[ cfg( windows) ]
68- use winapi:: shared:: ws2def:: AF_INET ;
69-
70- #[ cfg( not( windows) ) ]
71- use libc:: AF_INET6 ;
95+ use winapi:: shared:: in6addr:: in6_addr_u;
7296#[ cfg( windows) ]
73- use winapi:: shared:: ws2def:: AF_INET6 ;
97+ use winapi:: shared:: inaddr:: in_addr_S_un;
98+ #[ cfg( windows) ]
99+ use winapi:: shared:: ws2ipdef:: SOCKADDR_IN6_LH_u ;
74100
75101use crate :: * ;
76102
@@ -1259,54 +1285,155 @@ pub extern fn quiche_conn_send_quantum(conn: &mut Connection) -> size_t {
12591285}
12601286
12611287fn std_addr_from_c ( addr : & sockaddr , addr_len : socklen_t ) -> SocketAddr {
1262- unsafe {
1263- match addr. sa_family as i32 {
1264- AF_INET => {
1265- assert ! ( addr_len as usize == std:: mem:: size_of:: <sockaddr_in>( ) ) ;
1288+ match addr. sa_family as i32 {
1289+ AF_INET => {
1290+ assert ! ( addr_len as usize == std:: mem:: size_of:: <sockaddr_in>( ) ) ;
12661291
1267- SocketAddr :: V4 (
1268- * ( addr as * const _ as * const sockaddr_in as * const _ ) ,
1269- )
1270- } ,
1292+ let in4 = unsafe { * ( addr as * const _ as * const sockaddr_in ) } ;
12711293
1272- AF_INET6 => {
1273- assert ! ( addr_len as usize == std:: mem:: size_of:: <sockaddr_in6>( ) ) ;
1294+ #[ cfg( not( windows) ) ]
1295+ let ip_addr = Ipv4Addr :: from ( u32:: from_be ( in4. sin_addr . s_addr ) ) ;
1296+ #[ cfg( windows) ]
1297+ let ip_addr = {
1298+ let ip_bytes = unsafe { in4. sin_addr . S_un . S_un_b ( ) } ;
12741299
1275- SocketAddr :: V6 (
1276- * ( addr as * const _ as * const sockaddr_in6 as * const _ ) ,
1277- )
1278- } ,
1300+ Ipv4Addr :: from ( [
1301+ ip_bytes. s_b1 ,
1302+ ip_bytes. s_b2 ,
1303+ ip_bytes. s_b3 ,
1304+ ip_bytes. s_b4 ,
1305+ ] )
1306+ } ;
12791307
1280- _ => unimplemented ! ( "unsupported address type" ) ,
1281- }
1282- }
1283- }
1308+ let port = u16:: from_be ( in4. sin_port ) ;
12841309
1285- fn std_addr_to_c ( addr : & SocketAddr , out : & mut sockaddr_storage ) -> socklen_t {
1286- unsafe {
1287- match addr {
1288- SocketAddr :: V4 ( addr) => {
1289- let sa_len = std:: mem:: size_of :: < sockaddr_in > ( ) ;
1310+ let out = SocketAddrV4 :: new ( ip_addr, port) ;
1311+
1312+ out. into ( )
1313+ } ,
12901314
1291- let src = addr as * const _ as * const u8 ;
1292- let dst = out as * mut _ as * mut u8 ;
1315+ AF_INET6 => {
1316+ assert ! ( addr_len as usize == std :: mem :: size_of :: <sockaddr_in6> ( ) ) ;
12931317
1294- std :: ptr :: copy_nonoverlapping ( src , dst , sa_len ) ;
1318+ let in6 = unsafe { * ( addr as * const _ as * const sockaddr_in6 ) } ;
12951319
1296- sa_len as socklen_t
1297- } ,
1320+ let ip_addr = Ipv6Addr :: from (
1321+ #[ cfg( not( windows) ) ]
1322+ in6. sin6_addr . s6_addr ,
1323+ #[ cfg( windows) ]
1324+ * unsafe { in6. sin6_addr . u . Byte ( ) } ,
1325+ ) ;
12981326
1299- SocketAddr :: V6 ( addr) => {
1300- let sa_len = std:: mem:: size_of :: < sockaddr_in6 > ( ) ;
1327+ let port = u16:: from_be ( in6. sin6_port ) ;
13011328
1302- let src = addr as * const _ as * const u8 ;
1303- let dst = out as * mut _ as * mut u8 ;
1329+ #[ cfg( not( windows) ) ]
1330+ let scope_id = in6. sin6_scope_id ;
1331+ #[ cfg( windows) ]
1332+ let scope_id = unsafe { * in6. u . sin6_scope_id ( ) } ;
13041333
1305- std:: ptr:: copy_nonoverlapping ( src, dst, sa_len) ;
1334+ let out =
1335+ SocketAddrV6 :: new ( ip_addr, port, in6. sin6_flowinfo , scope_id) ;
13061336
1307- sa_len as socklen_t
1308- } ,
1309- }
1337+ out. into ( )
1338+ } ,
1339+
1340+ _ => unimplemented ! ( "unsupported address type" ) ,
1341+ }
1342+ }
1343+
1344+ fn std_addr_to_c ( addr : & SocketAddr , out : & mut sockaddr_storage ) -> socklen_t {
1345+ let sin_port = addr. port ( ) . to_be ( ) ;
1346+
1347+ match addr {
1348+ SocketAddr :: V4 ( addr) => unsafe {
1349+ let sa_len = std:: mem:: size_of :: < sockaddr_in > ( ) ;
1350+ let out_in = out as * mut _ as * mut sockaddr_in ;
1351+
1352+ let s_addr = u32:: from_ne_bytes ( addr. ip ( ) . octets ( ) ) ;
1353+
1354+ #[ cfg( not( windows) ) ]
1355+ let sin_addr = in_addr { s_addr } ;
1356+ #[ cfg( windows) ]
1357+ let sin_addr = {
1358+ let mut s_un = std:: mem:: zeroed :: < in_addr_S_un > ( ) ;
1359+ * s_un. S_addr_mut ( ) = s_addr;
1360+ in_addr { S_un : s_un }
1361+ } ;
1362+
1363+ * out_in = sockaddr_in {
1364+ sin_family : AF_INET as sa_family_t ,
1365+
1366+ sin_addr,
1367+
1368+ #[ cfg( any(
1369+ target_os = "macos" ,
1370+ target_os = "ios" ,
1371+ target_os = "watchos" ,
1372+ target_os = "freebsd" ,
1373+ target_os = "dragonfly" ,
1374+ target_os = "openbsd" ,
1375+ target_os = "netbsd"
1376+ ) ) ]
1377+ sin_len : sa_len as u8 ,
1378+
1379+ sin_port,
1380+
1381+ sin_zero : std:: mem:: zeroed ( ) ,
1382+ } ;
1383+
1384+ sa_len as socklen_t
1385+ } ,
1386+
1387+ SocketAddr :: V6 ( addr) => unsafe {
1388+ let sa_len = std:: mem:: size_of :: < sockaddr_in6 > ( ) ;
1389+ let out_in6 = out as * mut _ as * mut sockaddr_in6 ;
1390+
1391+ #[ cfg( not( windows) ) ]
1392+ let sin6_addr = in6_addr {
1393+ s6_addr : addr. ip ( ) . octets ( ) ,
1394+ } ;
1395+ #[ cfg( windows) ]
1396+ let sin6_addr = {
1397+ let mut u = std:: mem:: zeroed :: < in6_addr_u > ( ) ;
1398+ * u. Byte_mut ( ) = addr. ip ( ) . octets ( ) ;
1399+ in6_addr { u }
1400+ } ;
1401+
1402+ #[ cfg( windows) ]
1403+ let u = {
1404+ let mut u = std:: mem:: zeroed :: < SOCKADDR_IN6_LH_u > ( ) ;
1405+ * u. sin6_scope_id_mut ( ) = addr. scope_id ( ) ;
1406+ u
1407+ } ;
1408+
1409+ * out_in6 = sockaddr_in6 {
1410+ sin6_family : AF_INET6 as sa_family_t ,
1411+
1412+ sin6_addr,
1413+
1414+ #[ cfg( any(
1415+ target_os = "macos" ,
1416+ target_os = "ios" ,
1417+ target_os = "watchos" ,
1418+ target_os = "freebsd" ,
1419+ target_os = "dragonfly" ,
1420+ target_os = "openbsd" ,
1421+ target_os = "netbsd"
1422+ ) ) ]
1423+ sin6_len : sa_len as u8 ,
1424+
1425+ sin6_port : sin_port,
1426+
1427+ sin6_flowinfo : addr. flowinfo ( ) ,
1428+
1429+ #[ cfg( not( windows) ) ]
1430+ sin6_scope_id : addr. scope_id ( ) ,
1431+ #[ cfg( windows) ]
1432+ u,
1433+ } ;
1434+
1435+ sa_len as socklen_t
1436+ } ,
13101437 }
13111438}
13121439
@@ -1323,3 +1450,108 @@ fn std_time_to_c(_time: &std::time::Instant, out: &mut timespec) {
13231450 out. tv_sec = 0 ;
13241451 out. tv_nsec = 0 ;
13251452}
1453+
1454+ #[ cfg( test) ]
1455+ mod tests {
1456+ use super :: * ;
1457+
1458+ #[ cfg( windows) ]
1459+ use winapi:: um:: ws2tcpip:: inet_ntop;
1460+
1461+ #[ test]
1462+ fn addr_v4 ( ) {
1463+ let addr = "127.0.0.1:8080" . parse ( ) . unwrap ( ) ;
1464+
1465+ let mut out: sockaddr_storage = unsafe { std:: mem:: zeroed ( ) } ;
1466+
1467+ assert_eq ! (
1468+ std_addr_to_c( & addr, & mut out) ,
1469+ std:: mem:: size_of:: <sockaddr_in>( ) as socklen_t
1470+ ) ;
1471+
1472+ let s = std:: ffi:: CString :: new ( "ddd.ddd.ddd.ddd" ) . unwrap ( ) ;
1473+
1474+ let s = unsafe {
1475+ let in_addr = & out as * const _ as * const sockaddr_in ;
1476+ assert_eq ! ( u16 :: from_be( ( * in_addr) . sin_port) , addr. port( ) ) ;
1477+
1478+ let dst = s. into_raw ( ) ;
1479+
1480+ inet_ntop (
1481+ AF_INET ,
1482+ & ( ( * in_addr) . sin_addr ) as * const _ as * const c_void ,
1483+ dst,
1484+ 16 ,
1485+ ) ;
1486+
1487+ std:: ffi:: CString :: from_raw ( dst) . into_string ( ) . unwrap ( )
1488+ } ;
1489+
1490+ assert_eq ! ( s, "127.0.0.1" ) ;
1491+
1492+ let addr = unsafe {
1493+ std_addr_from_c (
1494+ & * ( & out as * const _ as * const sockaddr ) ,
1495+ std:: mem:: size_of :: < sockaddr_in > ( ) as socklen_t ,
1496+ )
1497+ } ;
1498+
1499+ assert_eq ! ( addr, "127.0.0.1:8080" . parse( ) . unwrap( ) ) ;
1500+ }
1501+
1502+ #[ test]
1503+ fn addr_v6 ( ) {
1504+ let addr = "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080"
1505+ . parse ( )
1506+ . unwrap ( ) ;
1507+
1508+ let mut out: sockaddr_storage = unsafe { std:: mem:: zeroed ( ) } ;
1509+
1510+ assert_eq ! (
1511+ std_addr_to_c( & addr, & mut out) ,
1512+ std:: mem:: size_of:: <sockaddr_in6>( ) as socklen_t
1513+ ) ;
1514+
1515+ let s = std:: ffi:: CString :: new ( "dddd:dddd:dddd:dddd:dddd:dddd:dddd:dddd" )
1516+ . unwrap ( ) ;
1517+
1518+ let s = unsafe {
1519+ let in6_addr = & out as * const _ as * const sockaddr_in6 ;
1520+ assert_eq ! ( u16 :: from_be( ( * in6_addr) . sin6_port) , addr. port( ) ) ;
1521+
1522+ let dst = s. into_raw ( ) ;
1523+
1524+ inet_ntop (
1525+ AF_INET6 ,
1526+ & ( ( * in6_addr) . sin6_addr ) as * const _ as * const c_void ,
1527+ dst,
1528+ 45 ,
1529+ ) ;
1530+
1531+ std:: ffi:: CString :: from_raw ( dst) . into_string ( ) . unwrap ( )
1532+ } ;
1533+
1534+ assert_eq ! ( s, "2001:db8:85a3::8a2e:370:7334" ) ;
1535+
1536+ let addr = unsafe {
1537+ std_addr_from_c (
1538+ & * ( & out as * const _ as * const sockaddr ) ,
1539+ std:: mem:: size_of :: < sockaddr_in6 > ( ) as socklen_t ,
1540+ )
1541+ } ;
1542+
1543+ assert_eq ! (
1544+ addr,
1545+ "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080"
1546+ . parse( )
1547+ . unwrap( )
1548+ ) ;
1549+ }
1550+
1551+ #[ cfg( not( windows) ) ]
1552+ extern {
1553+ fn inet_ntop (
1554+ af : c_int , src : * const c_void , dst : * mut c_char , size : socklen_t ,
1555+ ) -> * mut c_char ;
1556+ }
1557+ }
0 commit comments