// 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 }
func (d *afpacket) Write(from ethernet.Frame) (err error) { copy(d.sockaddrLL.Addr[:6], []byte(from.Destination())) err = unix.Sendto(d.fd, []byte(from), 0, d.sockaddrLL) if err != nil { return } return }
func (pc *packetSock) Write(packet []byte) error { lladdr := unix.SockaddrLinklayer{ Ifindex: pc.ifindex, Protocol: swap16(unix.ETH_P_IP), Halen: uint8(len(bcastMAC)), } copy(lladdr.Addr[:], bcastMAC) pkt := make([]byte, minIPHdrLen+udpHdrLen+len(packet)) fillIPHdr(pkt[0:minIPHdrLen], udpHdrLen+uint16(len(packet))) fillUDPHdr(pkt[minIPHdrLen:minIPHdrLen+udpHdrLen], uint16(len(packet))) // payload copy(pkt[minIPHdrLen+udpHdrLen:len(pkt)], packet) return unix.Sendto(pc.fd, pkt, 0, &lladdr) }
// TfoDial dials to addr using tcp protocol with fast open option set, // addr should be in the form of "addr:port", // the data is sent along with the first syn packet of tcp handshake. // It returns a established connection and an error if any. func tfoDial(addr string, data []byte) (conn net.Conn, err error) { fd, err := unix.Socket(unix.AF_INET, unix.SOCK_STREAM, 0) if err != nil { return } defer unix.Close(fd) sa, err := tcpAddrToSockaddr(addr) if err != nil { return } err = unix.Sendto(fd, data, unix.MSG_FASTOPEN, sa) if err != nil { return } f := os.NewFile(uintptr(fd), "TFODial") defer f.Close() return net.FileConn(f) }