Permalink
Browse files

Add TCP_INFO/TCP_CONNECTION_INFO queries. (#811)

Motivation:

Many users may wish to see the underlying TCP connection state for
important calculations, such as for BDP or RTT numbers. We can make this
available easily enough.

Modifications:

- Added a function to get TCP_INFO on Linux/FreeBSD.
- Added a function to get TCP_CONNECTION_INFO on Darwin.

Result:

Better connection stats
  • Loading branch information...
Lukasa authored and weissi committed Feb 11, 2019
1 parent 642076e commit 2738b6d54fca302e9bcf2eec20d629f75c7e6aca
@@ -207,6 +207,30 @@ public extension SocketOptionProvider {
func getIPv6MulticastLoop() -> EventLoopFuture<CUnsignedInt> {
return self.unsafeGetSocketOption(level: IPPROTO_IPV6, name: IPV6_MULTICAST_LOOP)
}

#if os(Linux) || os(FreeBSD)
/// Gets the value of the socket option TCP_INFO.
///
/// This socket option cannot be set.
///
/// - returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
func getTCPInfo() -> EventLoopFuture<tcp_info> {
return self.unsafeGetSocketOption(level: IPPROTO_TCP, name: TCP_INFO)
}
#endif

#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
/// Gets the value of the socket option TCP_CONNECTION_INFO.
///
/// This socket option cannot be set.
///
/// - returns: An `EventLoopFuture` containing the value of the socket option, or
/// any error that occurred while retrieving the socket option.
func getTCPConnectionInfo() -> EventLoopFuture<tcp_connection_info> {
return self.unsafeGetSocketOption(level: IPPROTO_TCP, name: TCP_CONNECTION_INFO)
}
#endif
}


@@ -38,6 +38,8 @@ extension SocketOptionProviderTest {
("testIpv6MulticastIf", testIpv6MulticastIf),
("testIPv6MulticastHops", testIPv6MulticastHops),
("testIPv6MulticastLoop", testIPv6MulticastLoop),
("testTCPInfo", testTCPInfo),
("testTCPConnectionInfo", testTCPConnectionInfo),
]
}
}
@@ -241,4 +241,26 @@ final class SocketOptionProviderTest: XCTestCase {
XCTAssertNotEqual($0, 0)
}.wait())
}

func testTCPInfo() throws {
// This test only runs on Linux and FreeBSD.
#if os(Linux) || os(FreeBSD)
let channel = self.clientChannel! as! SocketOptionProvider
let tcpInfo = try assertNoThrowWithValue(channel.getTCPInfo().wait())

// We just need to sanity check something here to ensure that the data is vaguely reasonable.
XCTAssertEqual(tcpInfo.tcpi_state, UInt8(TCP_ESTABLISHED))
#endif
}

func testTCPConnectionInfo() throws {
// This test only runs on Darwin.
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
let channel = self.clientChannel! as! SocketOptionProvider
let tcpConnectionInfo = try assertNoThrowWithValue(channel.getTCPConnectionInfo().wait())

// We just need to sanity check something here to ensure that the data is vaguely reasonable.
XCTAssertEqual(tcpConnectionInfo.tcpi_state, UInt8(TSI_S_ESTABLISHED))
#endif
}
}

0 comments on commit 2738b6d

Please sign in to comment.