}
}
+// WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4.
+func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (int, int, error) {
+ if err := fd.writeLock(); err != nil {
+ return 0, 0, err
+ }
+ defer fd.writeUnlock()
+ if err := fd.pd.prepareWrite(fd.isFile); err != nil {
+ return 0, 0, err
+ }
+ for {
+ n, err := unix.SendmsgNInet4(fd.Sysfd, p, oob, sa, 0)
+ 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 n, 0, err
+ }
+ return n, len(oob), err
+ }
+}
+
+// WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6.
+func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (int, int, error) {
+ if err := fd.writeLock(); err != nil {
+ return 0, 0, err
+ }
+ defer fd.writeUnlock()
+ if err := fd.pd.prepareWrite(fd.isFile); err != nil {
+ return 0, 0, err
+ }
+ for {
+ n, err := unix.SendmsgNInet6(fd.Sysfd, p, oob, sa, 0)
+ 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 n, 0, err
+ }
+ return n, len(oob), err
+ }
+}
+
// Accept wraps the accept network call.
func (fd *FD) Accept() (int, syscall.Sockaddr, string, error) {
if err := fd.readLock(); err != nil {
return syscall.EWINDOWS
}
+func sockaddrInet4ToRaw(sa syscall.SockaddrInet4) (unsafe.Pointer, int32) {
+ var raw syscall.RawSockaddrInet4
+ raw.Family = syscall.AF_INET
+ p := (*[2]byte)(unsafe.Pointer(&raw.Port))
+ p[0] = byte(sa.Port >> 8)
+ p[1] = byte(sa.Port)
+ raw.Addr = sa.Addr
+ return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw))
+}
+
+func sockaddrInet6ToRaw(sa syscall.SockaddrInet6) (unsafe.Pointer, int32) {
+ var raw syscall.RawSockaddrInet6
+ raw.Family = syscall.AF_INET6
+ p := (*[2]byte)(unsafe.Pointer(&raw.Port))
+ p[0] = byte(sa.Port >> 8)
+ p[1] = byte(sa.Port)
+ raw.Scope_id = sa.ZoneId
+ raw.Addr = sa.Addr
+ return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw))
+}
+
func sockaddrToRaw(sa syscall.Sockaddr) (unsafe.Pointer, int32, error) {
switch sa := sa.(type) {
case *syscall.SockaddrInet4:
- var raw syscall.RawSockaddrInet4
- raw.Family = syscall.AF_INET
- p := (*[2]byte)(unsafe.Pointer(&raw.Port))
- p[0] = byte(sa.Port >> 8)
- p[1] = byte(sa.Port)
- raw.Addr = sa.Addr
- return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil
+ ptr, sz := sockaddrInet4ToRaw(*sa)
+ return ptr, sz, nil
case *syscall.SockaddrInet6:
- var raw syscall.RawSockaddrInet6
- raw.Family = syscall.AF_INET6
- p := (*[2]byte)(unsafe.Pointer(&raw.Port))
- p[0] = byte(sa.Port >> 8)
- p[1] = byte(sa.Port)
- raw.Scope_id = sa.ZoneId
- raw.Addr = sa.Addr
- return unsafe.Pointer(&raw), int32(unsafe.Sizeof(raw)), nil
+ ptr, sz := sockaddrInet6ToRaw(*sa)
+ return ptr, sz, nil
default:
return nil, 0, syscall.EWINDOWS
}
})
return n, int(o.msg.Control.Len), err
}
+
+// WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4.
+func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (int, int, error) {
+ if len(p) > maxRW {
+ return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
+ }
+
+ if err := fd.writeLock(); err != nil {
+ return 0, 0, err
+ }
+ defer fd.writeUnlock()
+
+ o := &fd.wop
+ o.InitMsg(p, oob)
+ rsa, len := sockaddrInet4ToRaw(sa)
+ o.msg.Name = (syscall.Pointer)(rsa)
+ o.msg.Namelen = len
+ n, err := execIO(o, func(o *operation) error {
+ return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
+ })
+ return n, int(o.msg.Control.Len), err
+}
+
+// WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6.
+func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (int, int, error) {
+ if len(p) > maxRW {
+ return 0, 0, errors.New("packet is too large (only 1GB is allowed)")
+ }
+
+ if err := fd.writeLock(); err != nil {
+ return 0, 0, err
+ }
+ defer fd.writeUnlock()
+
+ o := &fd.wop
+ o.InitMsg(p, oob)
+ rsa, len := sockaddrInet6ToRaw(sa)
+ o.msg.Name = (syscall.Pointer)(rsa)
+ o.msg.Namelen = len
+ n, err := execIO(o, func(o *operation) error {
+ return windows.WSASendMsg(o.fd.Sysfd, &o.msg, 0, &o.qty, &o.o, nil)
+ })
+ return n, int(o.msg.Control.Len), err
+}
//go:linkname SendtoInet6 syscall.sendtoInet6
//go:noescape
func SendtoInet6(fd int, p []byte, flags int, to syscall.SockaddrInet6) (err error)
+
+//go:linkname SendmsgNInet4 syscall.sendmsgNInet4
+//go:noescape
+func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) (n int, err error)
+
+//go:linkname SendmsgNInet6 syscall.sendmsgNInet6
+//go:noescape
+func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error)
func SendtoInet6(fd int, p []byte, flags int, to syscall.SockaddrInet6) (err error) {
return syscall.ENOSYS
}
+
+func SendmsgNInet4(fd int, p, oob []byte, to syscall.SockaddrInet4, flags int) (n int, err error) {
+ return 0, syscall.ENOSYS
+}
+
+func SendmsgNInet6(fd int, p, oob []byte, to syscall.SockaddrInet6, flags int) (n int, err error) {
+ return 0, syscall.ENOSYS
+}
return n, oobn, wrapSyscallError(writeMsgSyscallName, err)
}
+func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) {
+ n, oobn, err = fd.pfd.WriteMsgInet4(p, oob, sa)
+ runtime.KeepAlive(fd)
+ return n, oobn, wrapSyscallError(writeMsgSyscallName, err)
+}
+
+func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (n int, oobn int, err error) {
+ n, oobn, err = fd.pfd.WriteMsgInet6(p, oob, sa)
+ runtime.KeepAlive(fd)
+ return n, oobn, wrapSyscallError(writeMsgSyscallName, err)
+}
+
func (fd *netFD) SetDeadline(t time.Time) error {
return fd.pfd.SetDeadline(t)
}
return 0, 0, 0, nil, syscall.ENOSYS
}
+func (fd *netFD) writeMsgInet4(p []byte, oob []byte, sa syscall.SockaddrInet4) (n int, oobn int, err error) {
+ return 0, 0, syscall.ENOSYS
+}
+
+func (fd *netFD) writeMsgInet6(p []byte, oob []byte, sa syscall.SockaddrInet6) (n int, oobn int, err error) {
+ return 0, 0, syscall.ENOSYS
+}
+
func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
return 0, syscall.ENOSYS
}
if err != nil {
return 0, 0, err
}
- // TODO: Implement writeMsgInet4 to avoid allocation converting sa to an interface.
- return c.fd.writeMsg(b, oob, &sa)
+ return c.fd.writeMsgInet4(b, oob, sa)
case syscall.AF_INET6:
sa, err := addrPortToSockaddrInet6(addr)
if err != nil {
return 0, 0, err
}
- // TODO: Implement writeMsgInet6 to avoid allocation converting sa to an interface.
- return c.fd.writeMsg(b, oob, &sa)
+ return c.fd.writeMsgInet6(b, oob, sa)
default:
return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()}
}
return sendmsgN(fd, p, oob, ptr, salen, flags)
}
+func sendmsgNInet4(fd int, p, oob []byte, to SockaddrInet4, flags int) (n int, err error) {
+ ptr, salen, err := to.sockaddr()
+ if err != nil {
+ return 0, err
+ }
+ return sendmsgN(fd, p, oob, ptr, salen, flags)
+}
+
+func sendmsgNInet6(fd int, p, oob []byte, to SockaddrInet6, flags int) (n int, err error) {
+ ptr, salen, err := to.sockaddr()
+ if err != nil {
+ return 0, err
+ }
+ return sendmsgN(fd, p, oob, ptr, salen, flags)
+}
+
func sendtoInet4(fd int, p []byte, flags int, to SockaddrInet4) (err error) {
ptr, n, err := to.sockaddr()
if err != nil {