Skip to content

Commit 9de2019

Browse files
committed
auto merge of #16251 : apoelstra/rust/tcp-fix, r=alexcrichton
Replacement for PR #16208 (make sockaddr* struct padding explicit) to make PR #15763 (fix nested returns) merge without breaking TCP code.
2 parents efe1f7e + 30452d4 commit 9de2019

File tree

3 files changed

+53
-47
lines changed

3 files changed

+53
-47
lines changed

src/libnative/io/net.rs

+18-17
Original file line numberDiff line numberDiff line change
@@ -66,26 +66,27 @@ fn ip_to_inaddr(ip: rtio::IpAddr) -> InAddr {
6666
}
6767
}
6868

69-
fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) {
69+
fn addr_to_sockaddr(addr: rtio::SocketAddr,
70+
storage: &mut libc::sockaddr_storage)
71+
-> libc::socklen_t {
7072
unsafe {
71-
let storage: libc::sockaddr_storage = mem::zeroed();
7273
let len = match ip_to_inaddr(addr.ip) {
7374
InAddr(inaddr) => {
74-
let storage: *mut libc::sockaddr_in = mem::transmute(&storage);
75+
let storage = storage as *mut _ as *mut libc::sockaddr_in;
7576
(*storage).sin_family = libc::AF_INET as libc::sa_family_t;
7677
(*storage).sin_port = htons(addr.port);
7778
(*storage).sin_addr = inaddr;
7879
mem::size_of::<libc::sockaddr_in>()
7980
}
8081
In6Addr(inaddr) => {
81-
let storage: *mut libc::sockaddr_in6 = mem::transmute(&storage);
82+
let storage = storage as *mut _ as *mut libc::sockaddr_in6;
8283
(*storage).sin6_family = libc::AF_INET6 as libc::sa_family_t;
8384
(*storage).sin6_port = htons(addr.port);
8485
(*storage).sin6_addr = inaddr;
8586
mem::size_of::<libc::sockaddr_in6>()
8687
}
8788
};
88-
return (storage, len);
89+
return len as libc::socklen_t;
8990
}
9091
}
9192

@@ -277,9 +278,9 @@ impl TcpStream {
277278
let fd = try!(socket(addr, libc::SOCK_STREAM));
278279
let ret = TcpStream::new(Inner::new(fd));
279280

280-
let (addr, len) = addr_to_sockaddr(addr);
281-
let addrp = &addr as *const _ as *const libc::sockaddr;
282-
let len = len as libc::socklen_t;
281+
let mut storage = unsafe { mem::zeroed() };
282+
let len = addr_to_sockaddr(addr, &mut storage);
283+
let addrp = &storage as *const _ as *const libc::sockaddr;
283284

284285
match timeout {
285286
Some(timeout) => {
@@ -457,9 +458,9 @@ impl TcpListener {
457458
let fd = try!(socket(addr, libc::SOCK_STREAM));
458459
let ret = TcpListener { inner: Inner::new(fd) };
459460

460-
let (addr, len) = addr_to_sockaddr(addr);
461-
let addrp = &addr as *const _ as *const libc::sockaddr;
462-
let len = len as libc::socklen_t;
461+
let mut storage = unsafe { mem::zeroed() };
462+
let len = addr_to_sockaddr(addr, &mut storage);
463+
let addrp = &storage as *const _ as *const libc::sockaddr;
463464

464465
// On platforms with Berkeley-derived sockets, this allows
465466
// to quickly rebind a socket, without needing to wait for
@@ -566,9 +567,9 @@ impl UdpSocket {
566567
write_deadline: 0,
567568
};
568569

569-
let (addr, len) = addr_to_sockaddr(addr);
570-
let addrp = &addr as *const _ as *const libc::sockaddr;
571-
let len = len as libc::socklen_t;
570+
let mut storage = unsafe { mem::zeroed() };
571+
let len = addr_to_sockaddr(addr, &mut storage);
572+
let addrp = &storage as *const _ as *const libc::sockaddr;
572573

573574
match unsafe { libc::bind(fd, addrp, len) } {
574575
-1 => Err(last_error()),
@@ -656,9 +657,9 @@ impl rtio::RtioUdpSocket for UdpSocket {
656657
}
657658

658659
fn send_to(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> IoResult<()> {
659-
let (dst, dstlen) = addr_to_sockaddr(dst);
660-
let dstp = &dst as *const _ as *const libc::sockaddr;
661-
let dstlen = dstlen as libc::socklen_t;
660+
let mut storage = unsafe { mem::zeroed() };
661+
let dstlen = addr_to_sockaddr(dst, &mut storage);
662+
let dstp = &storage as *const _ as *const libc::sockaddr;
662663

663664
let fd = self.fd();
664665
let dolock = || self.lock_nonblocking();

src/libnative/io/pipe_unix.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@ fn unix_socket(ty: libc::c_int) -> IoResult<fd_t> {
2929
}
3030
}
3131

32-
fn addr_to_sockaddr_un(addr: &CString) -> IoResult<(libc::sockaddr_storage, uint)> {
32+
fn addr_to_sockaddr_un(addr: &CString,
33+
storage: &mut libc::sockaddr_storage)
34+
-> IoResult<libc::socklen_t> {
3335
// the sun_path length is limited to SUN_LEN (with null)
3436
assert!(mem::size_of::<libc::sockaddr_storage>() >=
3537
mem::size_of::<libc::sockaddr_un>());
36-
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
37-
let s: &mut libc::sockaddr_un = unsafe { mem::transmute(&mut storage) };
38+
let s = unsafe { &mut *(storage as *mut _ as *mut libc::sockaddr_un) };
3839

3940
let len = addr.len();
4041
if len > s.sun_path.len() - 1 {
@@ -53,7 +54,7 @@ fn addr_to_sockaddr_un(addr: &CString) -> IoResult<(libc::sockaddr_storage, uint
5354

5455
// count the null terminator
5556
let len = mem::size_of::<libc::sa_family_t>() + len + 1;
56-
return Ok((storage, len));
57+
return Ok(len as libc::socklen_t);
5758
}
5859

5960
struct Inner {
@@ -76,10 +77,10 @@ impl Drop for Inner {
7677

7778
fn connect(addr: &CString, ty: libc::c_int,
7879
timeout: Option<u64>) -> IoResult<Inner> {
79-
let (addr, len) = try!(addr_to_sockaddr_un(addr));
80+
let mut storage = unsafe { mem::zeroed() };
81+
let len = try!(addr_to_sockaddr_un(addr, &mut storage));
8082
let inner = Inner::new(try!(unix_socket(ty)));
81-
let addrp = &addr as *const _ as *const libc::sockaddr;
82-
let len = len as libc::socklen_t;
83+
let addrp = &storage as *const _ as *const libc::sockaddr;
8384

8485
match timeout {
8586
None => {
@@ -96,11 +97,12 @@ fn connect(addr: &CString, ty: libc::c_int,
9697
}
9798

9899
fn bind(addr: &CString, ty: libc::c_int) -> IoResult<Inner> {
99-
let (addr, len) = try!(addr_to_sockaddr_un(addr));
100+
let mut storage = unsafe { mem::zeroed() };
101+
let len = try!(addr_to_sockaddr_un(addr, &mut storage));
100102
let inner = Inner::new(try!(unix_socket(ty)));
101-
let addrp = &addr as *const _;
103+
let addrp = &storage as *const _ as *const libc::sockaddr;
102104
match unsafe {
103-
libc::bind(inner.fd, addrp as *const _, len as libc::socklen_t)
105+
libc::bind(inner.fd, addrp, len)
104106
} {
105107
-1 => Err(super::last_error()),
106108
_ => Ok(inner)

src/librustuv/net.rs

+23-20
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,17 @@ pub fn sockaddr_to_addr(storage: &libc::sockaddr_storage,
7575
}
7676
}
7777

78-
fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) {
78+
fn addr_to_sockaddr(addr: rtio::SocketAddr,
79+
storage: &mut libc::sockaddr_storage)
80+
-> libc::socklen_t {
7981
unsafe {
80-
let mut storage: libc::sockaddr_storage = mem::zeroed();
8182
let len = match addr.ip {
8283
rtio::Ipv4Addr(a, b, c, d) => {
8384
let ip = (a as u32 << 24) |
8485
(b as u32 << 16) |
8586
(c as u32 << 8) |
8687
(d as u32 << 0);
87-
let storage: &mut libc::sockaddr_in =
88-
mem::transmute(&mut storage);
88+
let storage = storage as *mut _ as *mut libc::sockaddr_in;
8989
(*storage).sin_family = libc::AF_INET as libc::sa_family_t;
9090
(*storage).sin_port = htons(addr.port);
9191
(*storage).sin_addr = libc::in_addr {
@@ -95,11 +95,10 @@ fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) {
9595
mem::size_of::<libc::sockaddr_in>()
9696
}
9797
rtio::Ipv6Addr(a, b, c, d, e, f, g, h) => {
98-
let storage: &mut libc::sockaddr_in6 =
99-
mem::transmute(&mut storage);
100-
storage.sin6_family = libc::AF_INET6 as libc::sa_family_t;
101-
storage.sin6_port = htons(addr.port);
102-
storage.sin6_addr = libc::in6_addr {
98+
let storage = storage as *mut _ as *mut libc::sockaddr_in6;
99+
(*storage).sin6_family = libc::AF_INET6 as libc::sa_family_t;
100+
(*storage).sin6_port = htons(addr.port);
101+
(*storage).sin6_addr = libc::in6_addr {
103102
s6_addr: [
104103
htons(a),
105104
htons(b),
@@ -114,7 +113,7 @@ fn addr_to_sockaddr(addr: rtio::SocketAddr) -> (libc::sockaddr_storage, uint) {
114113
mem::size_of::<libc::sockaddr_in6>()
115114
}
116115
};
117-
return (storage, len);
116+
return len as libc::socklen_t
118117
}
119118
}
120119

@@ -203,8 +202,9 @@ impl TcpWatcher {
203202
timeout: Option<u64>) -> Result<TcpWatcher, UvError> {
204203
let tcp = TcpWatcher::new(io);
205204
let cx = ConnectCtx { status: -1, task: None, timer: None };
206-
let (addr, _len) = addr_to_sockaddr(address);
207-
let addr_p = &addr as *const _ as *const libc::sockaddr;
205+
let mut storage = unsafe { mem::zeroed() };
206+
let _len = addr_to_sockaddr(address, &mut storage);
207+
let addr_p = &storage as *const _ as *const libc::sockaddr;
208208
cx.connect(tcp, timeout, io, |req, tcp, cb| {
209209
unsafe { uvll::uv_tcp_connect(req.handle, tcp.handle, addr_p, cb) }
210210
})
@@ -361,10 +361,11 @@ impl TcpListener {
361361
outgoing: tx,
362362
incoming: rx,
363363
};
364-
let (addr, _len) = addr_to_sockaddr(address);
364+
let mut storage = unsafe { mem::zeroed() };
365+
let _len = addr_to_sockaddr(address, &mut storage);
365366
let res = unsafe {
366-
let addr_p = &addr as *const libc::sockaddr_storage;
367-
uvll::uv_tcp_bind(l.handle, addr_p as *const libc::sockaddr)
367+
let addr_p = &storage as *const _ as *const libc::sockaddr;
368+
uvll::uv_tcp_bind(l.handle, addr_p)
368369
};
369370
return match res {
370371
0 => Ok(l.install()),
@@ -513,10 +514,11 @@ impl UdpWatcher {
513514
assert_eq!(unsafe {
514515
uvll::uv_udp_init(io.uv_loop(), udp.handle)
515516
}, 0);
516-
let (addr, _len) = addr_to_sockaddr(address);
517+
let mut storage = unsafe { mem::zeroed() };
518+
let _len = addr_to_sockaddr(address, &mut storage);
517519
let result = unsafe {
518-
let addr_p = &addr as *const libc::sockaddr_storage;
519-
uvll::uv_udp_bind(udp.handle, addr_p as *const libc::sockaddr, 0u32)
520+
let addr_p = &storage as *const _ as *const libc::sockaddr;
521+
uvll::uv_udp_bind(udp.handle, addr_p, 0u32)
520522
};
521523
return match result {
522524
0 => Ok(udp),
@@ -614,8 +616,9 @@ impl rtio::RtioUdpSocket for UdpWatcher {
614616
let guard = try!(self.write_access.grant(m));
615617

616618
let mut req = Request::new(uvll::UV_UDP_SEND);
617-
let (addr, _len) = addr_to_sockaddr(dst);
618-
let addr_p = &addr as *const _ as *const libc::sockaddr;
619+
let mut storage = unsafe { mem::zeroed() };
620+
let _len = addr_to_sockaddr(dst, &mut storage);
621+
let addr_p = &storage as *const _ as *const libc::sockaddr;
619622

620623
// see comments in StreamWatcher::write for why we may allocate a buffer
621624
// here.

0 commit comments

Comments
 (0)