//go:build linux && (amd64 || arm64 || ppc64 || ppc64le || mips64 || mips64le || s390x || riscv64 || loong64) && !android && !e2e_testing
// +build linux
// +build amd64 arm64 ppc64 ppc64le mips64 mips64le s390x riscv64 loong64
// +build !android
// +build !e2e_testing

package udp

import (
	"golang.org/x/sys/unix"
)

type iovec struct {
	Base *byte
	Len  uint64
}

type msghdr struct {
	Name       *byte
	Namelen    uint32
	Pad0       [4]byte
	Iov        *iovec
	Iovlen     uint64
	Control    *byte
	Controllen uint64
	Flags      int32
	Pad1       [4]byte
}

type rawMessage struct {
	Hdr  msghdr
	Len  uint32
	Pad0 [4]byte
}

func (u *StdConn) PrepareRawMessages(n, bufSize, cmsgSpace int) ([]rawMessage, [][]byte, [][]byte, []byte) {
	msgs := make([]rawMessage, n)
	buffers := make([][]byte, n)
	names := make([][]byte, n)

	var cmsgs []byte
	if cmsgSpace > 0 {
		cmsgs = make([]byte, n*cmsgSpace)
	}

	for i := range msgs {
		buffers[i] = make([]byte, bufSize)
		names[i] = make([]byte, unix.SizeofSockaddrInet6)

		vs := []iovec{
			{Base: &buffers[i][0], Len: uint64(len(buffers[i]))},
		}

		msgs[i].Hdr.Iov = &vs[0]
		msgs[i].Hdr.Iovlen = uint64(len(vs))

		msgs[i].Hdr.Name = &names[i][0]
		msgs[i].Hdr.Namelen = uint32(len(names[i]))

		if cmsgSpace > 0 {
			msgs[i].Hdr.Control = &cmsgs[i*cmsgSpace]
			msgs[i].Hdr.Controllen = uint64(cmsgSpace)
		}
	}

	return msgs, buffers, names, cmsgs
}

func setIovLen(v *iovec, n int) {
	v.Len = uint64(n)
}

func setMsgIovlen(m *msghdr, n int) {
	m.Iovlen = uint64(n)
}

func setMsgControllen(m *msghdr, n int) {
	m.Controllen = uint64(n)
}

func setCmsgLen(h *unix.Cmsghdr, n int) {
	h.Len = uint64(n)
}
