Duplicate some code to avoid an interface.
name old time/op new time/op delta
WriteToReadFromUDP-8 6.38µs ±20% 5.59µs ±10% -12.38% (p=0.001 n=10+9)
name old alloc/op new alloc/op delta
WriteToReadFromUDP-8 64.0B ± 0% 32.0B ± 0% -50.00% (p=0.000 n=10+10)
name old allocs/op new allocs/op delta
WriteToReadFromUDP-8 2.00 ± 0% 1.00 ± 0% -50.00% (p=0.000 n=10+10)
Windows is temporarily stubbed out.
Updates #43451
Change-Id: Ied15ff92268c652cf445836e0446025eaeb60cc9
Reviewed-on: https://go-review.googlesource.com/c/go/+/331489
Trust: Josh Bleecher Snyder <josharian@gmail.com>
Trust: Damien Neil <dneil@google.com>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Damien Neil <dneil@google.com>
+pkg syscall (darwin-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (darwin-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (darwin-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (darwin-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (freebsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (freebsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (freebsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (freebsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (freebsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (freebsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (freebsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (linux-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (linux-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (linux-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (linux-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (linux-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (linux-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (linux-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-arm), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-arm), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-arm-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-arm-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-arm64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-arm64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (netbsd-arm64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (netbsd-arm64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (openbsd-386), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (openbsd-386), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (openbsd-386-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (openbsd-386-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (openbsd-amd64), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (openbsd-amd64), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
+pkg syscall (openbsd-amd64-cgo), func SendtoInet4(int, []uint8, int, SockaddrInet4) error
+pkg syscall (openbsd-amd64-cgo), func SendtoInet6(int, []uint8, int, SockaddrInet6) error
}
}
+// WriteToInet4 wraps the sendto network call for IPv4 addresses.
+func (fd *FD) WriteToInet4(p []byte, sa syscall.SockaddrInet4) (int, error) {
+ if err := fd.writeLock(); err != nil {
+ return 0, err
+ }
+ defer fd.writeUnlock()
+ if err := fd.pd.prepareWrite(fd.isFile); err != nil {
+ return 0, err
+ }
+ for {
+ err := syscall.SendtoInet4(fd.Sysfd, p, 0, sa)
+ if err == syscall.EINTR {
+ continue
+ }
+ if err == syscall.EAGAIN && fd.pd.pollable() {
+ if err = fd.pd.waitWrite(fd.isFile); err == nil {
+ continue
+ }
+ }
+ if err != nil {
+ return 0, err
+ }
+ return len(p), nil
+ }
+}
+
+// WriteToInet6 wraps the sendto network call for IPv6 addresses.
+func (fd *FD) WriteToInet6(p []byte, sa syscall.SockaddrInet6) (int, error) {
+ if err := fd.writeLock(); err != nil {
+ return 0, err
+ }
+ defer fd.writeUnlock()
+ if err := fd.pd.prepareWrite(fd.isFile); err != nil {
+ return 0, err
+ }
+ for {
+ err := syscall.SendtoInet6(fd.Sysfd, p, 0, sa)
+ if err == syscall.EINTR {
+ continue
+ }
+ if err == syscall.EAGAIN && fd.pd.pollable() {
+ if err = fd.pd.waitWrite(fd.isFile); err == nil {
+ continue
+ }
+ }
+ if err != nil {
+ return 0, err
+ }
+ return len(p), nil
+ }
+}
+
// WriteTo wraps the sendto network call.
func (fd *FD) WriteTo(p []byte, sa syscall.Sockaddr) (int, error) {
if err := fd.writeLock(); err != nil {
return ntotal, nil
}
+// WriteTo wraps the sendto network call for IPv4.
+func (fd *FD) WriteToInet4(buf []byte, sa syscall.SockaddrInet4) (int, error) {
+ return fd.WriteTo(buf, &sa)
+}
+
+// WriteTo wraps the sendto network call for IPv6.
+func (fd *FD) WriteToInet6(buf []byte, sa syscall.SockaddrInet6) (int, error) {
+ return fd.WriteTo(buf, &sa)
+}
+
// Call ConnectEx. This doesn't need any locking, since it is only
// called when the descriptor is first created. This is here rather
// than in the net package so that it can use fd.wop.
return n, wrapSyscallError(writeToSyscallName, err)
}
+func (fd *netFD) writeToInet4(p []byte, sa syscall.SockaddrInet4) (n int, err error) {
+ n, err = fd.pfd.WriteToInet4(p, sa)
+ runtime.KeepAlive(fd)
+ return n, wrapSyscallError(writeToSyscallName, err)
+}
+
+func (fd *netFD) writeToInet6(p []byte, sa syscall.SockaddrInet6) (n int, err error) {
+ n, err = fd.pfd.WriteToInet6(p, sa)
+ runtime.KeepAlive(fd)
+ return n, wrapSyscallError(writeToSyscallName, err)
+}
+
func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
n, oobn, err = fd.pfd.WriteMsg(p, oob, sa)
runtime.KeepAlive(fd)
return socket(ctx, net, family, sotype, proto, ipv6only, laddr, raddr, ctrlFn)
}
+func ipToSockaddrInet4(ip IP, port int) (syscall.SockaddrInet4, error) {
+ if len(ip) == 0 {
+ ip = IPv4zero
+ }
+ ip4 := ip.To4()
+ if ip4 == nil {
+ return syscall.SockaddrInet4{}, &AddrError{Err: "non-IPv4 address", Addr: ip.String()}
+ }
+ sa := syscall.SockaddrInet4{Port: port}
+ copy(sa.Addr[:], ip4)
+ return sa, nil
+}
+
+func ipToSockaddrInet6(ip IP, port int, zone string) (syscall.SockaddrInet6, error) {
+ // In general, an IP wildcard address, which is either
+ // "0.0.0.0" or "::", means the entire IP addressing
+ // space. For some historical reason, it is used to
+ // specify "any available address" on some operations
+ // of IP node.
+ //
+ // When the IP node supports IPv4-mapped IPv6 address,
+ // we allow a listener to listen to the wildcard
+ // address of both IP addressing spaces by specifying
+ // IPv6 wildcard address.
+ if len(ip) == 0 || ip.Equal(IPv4zero) {
+ ip = IPv6zero
+ }
+ // We accept any IPv6 address including IPv4-mapped
+ // IPv6 address.
+ ip6 := ip.To16()
+ if ip6 == nil {
+ return syscall.SockaddrInet6{}, &AddrError{Err: "non-IPv6 address", Addr: ip.String()}
+ }
+ sa := syscall.SockaddrInet6{Port: port, ZoneId: uint32(zoneCache.index(zone))}
+ copy(sa.Addr[:], ip6)
+ return sa, nil
+}
+
func ipToSockaddr(family int, ip IP, port int, zone string) (syscall.Sockaddr, error) {
switch family {
case syscall.AF_INET:
- if len(ip) == 0 {
- ip = IPv4zero
- }
- ip4 := ip.To4()
- if ip4 == nil {
- return nil, &AddrError{Err: "non-IPv4 address", Addr: ip.String()}
+ sa, err := ipToSockaddrInet4(ip, port)
+ if err != nil {
+ return nil, err
}
- sa := &syscall.SockaddrInet4{Port: port}
- copy(sa.Addr[:], ip4)
- return sa, nil
+ return &sa, nil
case syscall.AF_INET6:
- // In general, an IP wildcard address, which is either
- // "0.0.0.0" or "::", means the entire IP addressing
- // space. For some historical reason, it is used to
- // specify "any available address" on some operations
- // of IP node.
- //
- // When the IP node supports IPv4-mapped IPv6 address,
- // we allow a listener to listen to the wildcard
- // address of both IP addressing spaces by specifying
- // IPv6 wildcard address.
- if len(ip) == 0 || ip.Equal(IPv4zero) {
- ip = IPv6zero
- }
- // We accept any IPv6 address including IPv4-mapped
- // IPv6 address.
- ip6 := ip.To16()
- if ip6 == nil {
- return nil, &AddrError{Err: "non-IPv6 address", Addr: ip.String()}
+ sa, err := ipToSockaddrInet6(ip, port, zone)
+ if err != nil {
+ return nil, err
}
- sa := &syscall.SockaddrInet6{Port: port, ZoneId: uint32(zoneCache.index(zone))}
- copy(sa.Addr[:], ip6)
- return sa, nil
+ return &sa, nil
}
return nil, &AddrError{Err: "invalid address family", Addr: ip.String()}
}
return 0, syscall.ENOSYS
}
+func (fd *netFD) writeToInet4(p []byte, sa syscall.SockaddrInet4) (n int, err error) {
+ return 0, syscall.ENOSYS
+}
+
+func (fd *netFD) writeToInet6(p []byte, sa syscall.SockaddrInet6) (n int, err error) {
+ return 0, syscall.ENOSYS
+}
+
func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
return 0, 0, syscall.ENOSYS
}
if addr == nil {
return 0, errMissingAddress
}
- sa, err := addr.sockaddr(c.fd.family)
- if err != nil {
- return 0, err
+
+ switch c.fd.family {
+ case syscall.AF_INET:
+ sa, err := ipToSockaddrInet4(addr.IP, addr.Port)
+ if err != nil {
+ return 0, err
+ }
+ return c.fd.writeToInet4(b, sa)
+ case syscall.AF_INET6:
+ sa, err := ipToSockaddrInet6(addr.IP, addr.Port, addr.Zone)
+ if err != nil {
+ return 0, err
+ }
+ return c.fd.writeToInet6(b, sa)
+ default:
+ return 0, &AddrError{Err: "invalid address family", Addr: addr.IP.String()}
}
- return c.fd.writeTo(b, sa)
}
func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
return ENOSYS
}
+func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) error {
+ return ENOSYS
+}
+
+func SendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) error {
+ return ENOSYS
+}
+
func Recvmsg(fd int, p, oob []byte, flags int) (n, oobn, recvflags int, from Sockaddr, err error) {
return 0, 0, 0, nil, ENOSYS
}
return
}
+func SendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) {
+ ptr, n, err := to.sockaddr()
+ if err != nil {
+ return err
+ }
+ return sendto(fd, p, flags, ptr, n)
+}
+
+func SendtoInet6(fd int, p []byte, flags int, to SockaddrInet6) (err error) {
+ ptr, n, err := to.sockaddr()
+ if err != nil {
+ return err
+ }
+ return sendto(fd, p, flags, ptr, n)
+}
+
func Sendto(fd int, p []byte, flags int, to Sockaddr) (err error) {
ptr, n, err := to.sockaddr()
if err != nil {