pkg net, method (*Dialer) MultipathTCP() bool #56539
pkg net, method (*Dialer) SetMultipathTCP(bool) #56539
+pkg net, method (*ListenConfig) MultipathTCP() bool #56539
+pkg net, method (*ListenConfig) SetMultipathTCP(bool) #56539
// that do not support keep-alives ignore this field.
// If negative, keep-alives are disabled.
KeepAlive time.Duration
+
+ // If mptcpStatus is set to a value allowing Multipath TCP (MPTCP) to be
+ // used, any call to Listen with "tcp(4|6)" as network will use MPTCP if
+ // supported by the operating system.
+ mptcpStatus mptcpStatus
+}
+
+// MultipathTCP reports whether MPTCP will be used.
+//
+// This method doesn't check if MPTCP is supported by the operating
+// system or not.
+func (lc *ListenConfig) MultipathTCP() bool {
+ return lc.mptcpStatus.get()
+}
+
+// SetMultipathTCP directs the Listen method to use, or not use, MPTCP,
+// if supported by the operating system. This method overrides the
+// system default.
+//
+// If MPTCP is not available on the host or not supported by the client,
+// the Listen method will fall back to TCP.
+func (lc *ListenConfig) SetMultipathTCP(use bool) {
+ lc.mptcpStatus.set(use)
}
// Listen announces on the local network address.
la := addrs.first(isIPv4)
switch la := la.(type) {
case *TCPAddr:
- l, err = sl.listenTCP(ctx, la)
+ if sl.MultipathTCP() {
+ l, err = sl.listenMPTCP(ctx, la)
+ } else {
+ l, err = sl.listenTCP(ctx, la)
+ }
case *UnixAddr:
l, err = sl.listenUnix(ctx, la)
default:
return sd.doDialTCPProto(ctx, laddr, raddr, _IPPROTO_MPTCP)
}
+
+func (sl *sysListener) listenMPTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
+ // Fallback to listenTCP if Multipath TCP isn't supported on this operating system.
+ if !supportsMultipathTCP() {
+ return sl.listenTCP(ctx, laddr)
+ }
+
+ return sl.listenTCPProto(ctx, laddr, _IPPROTO_MPTCP)
+}
func (sd *sysDialer) dialMPTCP(ctx context.Context, laddr, raddr *TCPAddr) (*TCPConn, error) {
return sd.dialTCP(ctx, laddr, raddr)
}
+
+func (sl *sysListener) listenMPTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
+ return sl.listenTCP(ctx, laddr)
+}
}
func (sl *sysListener) listenTCP(ctx context.Context, laddr *TCPAddr) (*TCPListener, error) {
+ return sl.listenTCPProto(ctx, laddr, 0)
+}
+
+func (sl *sysListener) listenTCPProto(ctx context.Context, laddr *TCPAddr, proto int) (*TCPListener, error) {
var ctrlCtxFn func(cxt context.Context, network, address string, c syscall.RawConn) error
if sl.ListenConfig.Control != nil {
ctrlCtxFn = func(cxt context.Context, network, address string, c syscall.RawConn) error {
return sl.ListenConfig.Control(network, address, c)
}
}
- fd, err := internetSocket(ctx, sl.network, laddr, nil, syscall.SOCK_STREAM, 0, "listen", ctrlCtxFn)
+ fd, err := internetSocket(ctx, sl.network, laddr, nil, syscall.SOCK_STREAM, proto, "listen", ctrlCtxFn)
if err != nil {
return nil, err
}