// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build aix || linux || netbsd

package socket

import (
	
	
	
	
)

type mmsghdrs []mmsghdr

func ( mmsghdrs) ( []Message,  func([]byte, string) (net.Addr, error),  string) error {
	for  := range  {
		[].N = int([].Len)
		[].NN = [].Hdr.controllen()
		[].Flags = [].Hdr.flags()
		if  != nil {
			var  error
			[].Addr,  = ([].Hdr.name(), )
			if  != nil {
				return 
			}
		}
	}
	return nil
}

// mmsghdrsPacker packs Message-slices into mmsghdrs (re-)using pre-allocated buffers.
type mmsghdrsPacker struct {
	// hs are the pre-allocated mmsghdrs.
	hs mmsghdrs
	// sockaddrs is the pre-allocated buffer for the Hdr.Name buffers.
	// We use one large buffer for all messages and slice it up.
	sockaddrs []byte
	// vs are the pre-allocated iovecs.
	// We allocate one large buffer for all messages and slice it up. This allows to reuse the buffer
	// if the number of buffers per message is distributed differently between calls.
	vs []iovec
}

func ( *mmsghdrsPacker) ( []Message) {
	 := len()
	if  <= cap(.hs) {
		.hs = .hs[:]
	} else {
		.hs = make(mmsghdrs, )
	}
	if *sizeofSockaddrInet6 <= cap(.sockaddrs) {
		.sockaddrs = .sockaddrs[:*sizeofSockaddrInet6]
	} else {
		.sockaddrs = make([]byte, *sizeofSockaddrInet6)
	}

	 := 0
	for ,  := range  {
		 += len(.Buffers)
	}
	if  <= cap(.vs) {
		.vs = .vs[:]
	} else {
		.vs = make([]iovec, )
	}
}

func ( *mmsghdrsPacker) ( []Message,  func([]byte, string) (net.Addr, error),  func(net.Addr, []byte) int) mmsghdrs {
	.prepare()
	 := .hs
	 := .vs
	 := .sockaddrs
	for  := range  {
		 := len([].Buffers)
		 := [:]
		 = [:]

		var  []byte
		if  != nil {
			 = [:sizeofSockaddrInet6]
			 = [sizeofSockaddrInet6:]
		} else if  != nil {
			 := ([].Addr, )
			if  > 0 {
				 = [:]
				 = [:]
			}
		}
		[].Hdr.pack(, [].Buffers, [].OOB, )
	}
	return 
}

// syscaller is a helper to invoke recvmmsg and sendmmsg via the RawConn.Read/Write interface.
// It is reusable, to amortize the overhead of allocating a closure for the function passed to
// RawConn.Read/Write.
type syscaller struct {
	n     int
	operr error
	hs    mmsghdrs
	flags int

	boundRecvmmsgF func(uintptr) bool
	boundSendmmsgF func(uintptr) bool
}

func ( *syscaller) () {
	.boundRecvmmsgF = .recvmmsgF
	.boundSendmmsgF = .sendmmsgF
}

func ( *syscaller) ( syscall.RawConn,  mmsghdrs,  int) (int, error) {
	.n = 0
	.operr = nil
	.hs = 
	.flags = 
	if  := .Read(.boundRecvmmsgF);  != nil {
		return .n, 
	}
	if .operr != nil {
		return .n, os.NewSyscallError("recvmmsg", .operr)
	}
	return .n, nil
}

func ( *syscaller) ( uintptr) bool {
	.n, .operr = recvmmsg(, .hs, .flags)
	return ioComplete(.flags, .operr)
}

func ( *syscaller) ( syscall.RawConn,  mmsghdrs,  int) (int, error) {
	.n = 0
	.operr = nil
	.hs = 
	.flags = 
	if  := .Write(.boundSendmmsgF);  != nil {
		return .n, 
	}
	if .operr != nil {
		return .n, os.NewSyscallError("sendmmsg", .operr)
	}
	return .n, nil
}

func ( *syscaller) ( uintptr) bool {
	.n, .operr = sendmmsg(, .hs, .flags)
	return ioComplete(.flags, .operr)
}

// mmsgTmps holds reusable temporary helpers for recvmmsg and sendmmsg.
type mmsgTmps struct {
	packer    mmsghdrsPacker
	syscaller syscaller
}

var defaultMmsgTmpsPool = mmsgTmpsPool{
	p: sync.Pool{
		New: func() interface{} {
			 := new(mmsgTmps)
			.syscaller.init()
			return 
		},
	},
}

type mmsgTmpsPool struct {
	p sync.Pool
}

func ( *mmsgTmpsPool) () *mmsgTmps {
	 := .p.Get().(*mmsgTmps)
	// Clear fields up to the len (not the cap) of the slice,
	// assuming that the previous caller only used that many elements.
	for  := range .packer.sockaddrs {
		.packer.sockaddrs[] = 0
	}
	.packer.sockaddrs = .packer.sockaddrs[:0]
	for  := range .packer.vs {
		.packer.vs[] = iovec{}
	}
	.packer.vs = .packer.vs[:0]
	for  := range .packer.hs {
		.packer.hs[].Len = 0
		.packer.hs[].Hdr = msghdr{}
	}
	.packer.hs = .packer.hs[:0]
	return 
}

func ( *mmsgTmpsPool) ( *mmsgTmps) {
	.p.Put()
}