Skip to content

Commit c3b0cdf

Browse files
authored
Enable TcpMaxSeg socket option for apple targets (#2603)
1 parent ea012be commit c3b0cdf

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

Diff for: changelog/2603.added.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added the TcpMaxSeg `setsockopt` option for apple targets

Diff for: src/sys/socket/sockopt.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ sockopt_impl!(
698698
u32
699699
);
700700
cfg_if! {
701-
if #[cfg(linux_android)] {
701+
if #[cfg(any(linux_android, apple_targets))] {
702702
sockopt_impl!(
703703
/// The maximum segment size for outgoing TCP packets.
704704
TcpMaxSeg, Both, libc::IPPROTO_TCP, libc::TCP_MAXSEG, u32);

Diff for: test/sys/test_sockopt.rs

+30-15
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,6 @@ fn test_so_tcp_maxseg() {
164164
use nix::sys::socket::{
165165
accept, bind, connect, getsockname, listen, Backlog, SockaddrIn,
166166
};
167-
use nix::unistd::write;
168167
use std::net::SocketAddrV4;
169168
use std::str::FromStr;
170169

@@ -184,14 +183,12 @@ fn test_so_tcp_maxseg() {
184183
let initial = getsockopt(&rsock, sockopt::TcpMaxSeg).unwrap();
185184
// Initial MSS is expected to be 536 (https://tools.ietf.org/html/rfc879#section-1) but some
186185
// platforms keep it even lower. This might fail if you've tuned your initial MSS to be larger
187-
// than 700
186+
// than `segsize`
187+
let segsize: u32 = 873;
188+
assert!(initial < segsize);
188189
cfg_if! {
189190
if #[cfg(linux_android)] {
190-
let segsize: u32 = 873;
191-
assert!(initial < segsize);
192191
setsockopt(&rsock, sockopt::TcpMaxSeg, &segsize).unwrap();
193-
} else {
194-
assert!(initial < 700);
195192
}
196193
}
197194

@@ -203,20 +200,38 @@ fn test_so_tcp_maxseg() {
203200
SockProtocol::Tcp,
204201
)
205202
.unwrap();
203+
206204
connect(ssock.as_raw_fd(), &sock_addr).unwrap();
205+
207206
let rsess = accept(rsock.as_raw_fd()).unwrap();
208207
let rsess = unsafe { OwnedFd::from_raw_fd(rsess) };
209-
write(&rsess, b"hello").unwrap();
210-
let actual = getsockopt(&ssock, sockopt::TcpMaxSeg).unwrap();
211-
// Actual max segment size takes header lengths into account, max IPv4 options (60 bytes) + max
212-
// TCP options (40 bytes) are subtracted from the requested maximum as a lower boundary.
208+
213209
cfg_if! {
214-
if #[cfg(linux_android)] {
215-
assert!((segsize - 100) <= actual);
216-
assert!(actual <= segsize);
210+
if #[cfg(apple_targets)] {
211+
// on apple targets (and unlike linux), we can only set the MSS on a *connected*
212+
// socket. Also, the same MSS can't be read using getsockopt from the other end.
213+
214+
assert_ne!(segsize, getsockopt(&rsess, sockopt::TcpMaxSeg).unwrap());
215+
setsockopt(&rsess, sockopt::TcpMaxSeg, &segsize).unwrap();
216+
assert_eq!(segsize, getsockopt(&rsess, sockopt::TcpMaxSeg).unwrap());
217+
218+
assert_ne!(segsize, getsockopt(&ssock, sockopt::TcpMaxSeg).unwrap());
219+
setsockopt(&ssock, sockopt::TcpMaxSeg, &segsize).unwrap();
220+
assert_eq!(segsize, getsockopt(&ssock, sockopt::TcpMaxSeg).unwrap());
217221
} else {
218-
assert!(initial < actual);
219-
assert!(536 < actual);
222+
use nix::unistd::write;
223+
224+
write(&rsess, b"hello").unwrap();
225+
let actual = getsockopt(&ssock, sockopt::TcpMaxSeg).unwrap();
226+
// Actual max segment size takes header lengths into account, max IPv4 options (60 bytes) + max
227+
// TCP options (40 bytes) are subtracted from the requested maximum as a lower boundary.
228+
if cfg!(linux_android) {
229+
assert!((segsize - 100) <= actual);
230+
assert!(actual <= segsize);
231+
} else {
232+
assert!(initial < actual);
233+
assert!(536 < actual);
234+
}
220235
}
221236
}
222237
}

0 commit comments

Comments
 (0)