// Copyright 2009 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 || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris || windows

package net

import (
	"context"
	"net/netip"
	"syscall"
)

func sockaddrToUDP(sa syscall.Sockaddr) Addr {
	switch sa := sa.(type) {
	case *syscall.SockaddrInet4:
		return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port}
	case *syscall.SockaddrInet6:
		return &UDPAddr{IP: sa.Addr[0:], Port: sa.Port, Zone: zoneCache.name(int(sa.ZoneId))}
	}
	return nil
}

func (a *UDPAddr) family() int {
	if a == nil || len(a.IP) <= IPv4len {
		return syscall.AF_INET
	}
	if a.IP.To4() != nil {
		return syscall.AF_INET
	}
	return syscall.AF_INET6
}

func (a *UDPAddr) sockaddr(family int) (syscall.Sockaddr, error) {
	if a == nil {
		return nil, nil
	}
	return ipToSockaddr(family, a.IP, a.Port, a.Zone)
}

func (a *UDPAddr) toLocal(net string) sockaddr {
	return &UDPAddr{loopbackIP(net), a.Port, a.Zone}
}

func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) {
	var n int
	var err error
	switch c.fd.family {
	case syscall.AF_INET:
		var from syscall.SockaddrInet4
		n, err = c.fd.readFromInet4(b, &from)
		if err == nil {
			ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 4 bytes
			*addr = UDPAddr{IP: ip[:], Port: from.Port}
		}
	case syscall.AF_INET6:
		var from syscall.SockaddrInet6
		n, err = c.fd.readFromInet6(b, &from)
		if err == nil {
			ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 16 bytes
			*addr = UDPAddr{IP: ip[:], Port: from.Port, Zone: zoneCache.name(int(from.ZoneId))}
		}
	}
	if err != nil {
		// No sockaddr, so don't return UDPAddr.
		addr = nil
	}
	return n, addr, err
}

func (c *UDPConn) readFromAddrPort(b []byte) (n int, addr netip.AddrPort, err error) {
	var ip netip.Addr
	var port int
	switch c.fd.family {
	case syscall.AF_INET:
		var from syscall.SockaddrInet4
		n, err = c.fd.readFromInet4(b, &from)
		if err == nil {
			ip = netip.AddrFrom4(from.Addr)
			port = from.Port
		}
	case syscall.AF_INET6:
		var from syscall.SockaddrInet6
		n, err = c.fd.readFromInet6(b, &from)
		if err == nil {
			ip = netip.AddrFrom16(from.Addr).WithZone(zoneCache.name(int(from.ZoneId)))
			port = from.Port
		}
	}
	if err == nil {
		addr = netip.AddrPortFrom(ip, uint16(port))
	}
	return n, addr, err
}

func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr netip.AddrPort, err error) {
	switch c.fd.family {
	case syscall.AF_INET:
		var sa syscall.SockaddrInet4
		n, oobn, flags, err = c.fd.readMsgInet4(b, oob, 0, &sa)
		ip := netip.AddrFrom4(sa.Addr)
		addr = netip.AddrPortFrom(ip, uint16(sa.Port))
	case syscall.AF_INET6:
		var sa syscall.SockaddrInet6
		n, oobn, flags, err = c.fd.readMsgInet6(b, oob, 0, &sa)
		ip := netip.AddrFrom16(sa.Addr).WithZone(zoneCache.name(int(sa.ZoneId)))
		addr = netip.AddrPortFrom(ip, uint16(sa.Port))
	}
	return
}

func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) {
	if c.fd.isConnected {
		return 0, ErrWriteToConnected
	}
	if addr == nil {
		return 0, errMissingAddress
	}

	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()}
	}
}

func (c *UDPConn) writeToAddrPort(b []byte, addr netip.AddrPort) (int, error) {
	if c.fd.isConnected {
		return 0, ErrWriteToConnected
	}
	if !addr.IsValid() {
		return 0, errMissingAddress
	}

	switch c.fd.family {
	case syscall.AF_INET:
		sa, err := addrPortToSockaddrInet4(addr)
		if err != nil {
			return 0, err
		}
		return c.fd.writeToInet4(b, &sa)
	case syscall.AF_INET6:
		sa, err := addrPortToSockaddrInet6(addr)
		if err != nil {
			return 0, err
		}
		return c.fd.writeToInet6(b, &sa)
	default:
		return 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()}
	}
}

func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) {
	if c.fd.isConnected && addr != nil {
		return 0, 0, ErrWriteToConnected
	}
	if !c.fd.isConnected && addr == nil {
		return 0, 0, errMissingAddress
	}
	sa, err := addr.sockaddr(c.fd.family)
	if err != nil {
		return 0, 0, err
	}
	return c.fd.writeMsg(b, oob, sa)
}

func (c *UDPConn) writeMsgAddrPort(b, oob []byte, addr netip.AddrPort) (n, oobn int, err error) {
	if c.fd.isConnected && addr.IsValid() {
		return 0, 0, ErrWriteToConnected
	}
	if !c.fd.isConnected && !addr.IsValid() {
		return 0, 0, errMissingAddress
	}

	switch c.fd.family {
	case syscall.AF_INET:
		sa, err := addrPortToSockaddrInet4(addr)
		if err != nil {
			return 0, 0, err
		}
		return c.fd.writeMsgInet4(b, oob, &sa)
	case syscall.AF_INET6:
		sa, err := addrPortToSockaddrInet6(addr)
		if err != nil {
			return 0, 0, err
		}
		return c.fd.writeMsgInet6(b, oob, &sa)
	default:
		return 0, 0, &AddrError{Err: "invalid address family", Addr: addr.Addr().String()}
	}
}

func (sd *sysDialer) dialUDP(ctx context.Context, laddr, raddr *UDPAddr) (*UDPConn, error) {
	fd, err := internetSocket(ctx, sd.network, laddr, raddr, syscall.SOCK_DGRAM, 0, "dial", sd.Dialer.Control)
	if err != nil {
		return nil, err
	}
	return newUDPConn(fd), nil
}

func (sl *sysListener) listenUDP(ctx context.Context, laddr *UDPAddr) (*UDPConn, error) {
	fd, err := internetSocket(ctx, sl.network, laddr, nil, syscall.SOCK_DGRAM, 0, "listen", sl.ListenConfig.Control)
	if err != nil {
		return nil, err
	}
	return newUDPConn(fd), nil
}

func (sl *sysListener) listenMulticastUDP(ctx context.Context, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) {
	fd, err := internetSocket(ctx, sl.network, gaddr, nil, syscall.SOCK_DGRAM, 0, "listen", sl.ListenConfig.Control)
	if err != nil {
		return nil, err
	}
	c := newUDPConn(fd)
	if ip4 := gaddr.IP.To4(); ip4 != nil {
		if err := listenIPv4MulticastUDP(c, ifi, ip4); err != nil {
			c.Close()
			return nil, err
		}
	} else {
		if err := listenIPv6MulticastUDP(c, ifi, gaddr.IP); err != nil {
			c.Close()
			return nil, err
		}
	}
	return c, nil
}

func listenIPv4MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
	if ifi != nil {
		if err := setIPv4MulticastInterface(c.fd, ifi); err != nil {
			return err
		}
	}
	if err := setIPv4MulticastLoopback(c.fd, false); err != nil {
		return err
	}
	if err := joinIPv4Group(c.fd, ifi, ip); err != nil {
		return err
	}
	return nil
}

func listenIPv6MulticastUDP(c *UDPConn, ifi *Interface, ip IP) error {
	if ifi != nil {
		if err := setIPv6MulticastInterface(c.fd, ifi); err != nil {
			return err
		}
	}
	if err := setIPv6MulticastLoopback(c.fd, false); err != nil {
		return err
	}
	if err := joinIPv6Group(c.fd, ifi, ip); err != nil {
		return err
	}
	return nil
}
