// dial tcp with tcp fastopen // 第一个包体积不要太大,需要小于一定数量,否则会被吃掉(正确性问题), // 如果过大,此处会在连接时发送前一部分,连接后又发送一部分 func TfoDial(nextAddr string, data []byte) (conn net.Conn, err error) { s, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0) if err != nil { return nil, err } defer unix.Close(s) sa, err := kmgUnix.IPv4TcpAddrToUnixSocksAddr(nextAddr) if err != nil { return nil, err } if len(data) <= tfoFirstSize { err = unix.Sendto(s, data, unix.MSG_FASTOPEN, sa) if err != nil { return } } else { err = unix.Sendto(s, data[:tfoFirstSize], unix.MSG_FASTOPEN, sa) if err != nil { return } } f := os.NewFile(uintptr(s), "TFODial") defer f.Close() conn, err = net.FileConn(f) if err != nil { return } if len(data) > tfoFirstSize { _, err = conn.Write(data[tfoFirstSize:]) if err != nil { return nil, err } } return conn, nil }
//network is useless ,it will always use tcp4 func TfoListen(network string, listenAddr string) (listener net.Listener, err error) { s, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM|unix.SOCK_NONBLOCK|unix.SOCK_CLOEXEC, 0) if err != nil { return nil, err } defer unix.Close(s) err = unix.SetsockoptInt(s, unix.SOL_TCP, 23, 10) if err != nil { return nil, err } err = unix.SetsockoptInt(s, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1) if err != nil { return nil, err } sa, err := kmgUnix.IPv4TcpAddrToUnixSocksAddr(listenAddr) if err != nil { return nil, err } err = unix.Bind(s, sa) if err != nil { return nil, err } err = unix.Listen(s, 10) if err != nil { return nil, err } f := os.NewFile(uintptr(s), "TFOListen") defer f.Close() return net.FileListener(f) }