1// +build !windows,!plan9
2
3package dns
4
5import (
6	"net"
7	"syscall"
8)
9
10// SessionUDP holds the remote address and the associated
11// out-of-band data.
12type SessionUDP struct {
13	raddr   *net.UDPAddr
14	context []byte
15}
16
17// RemoteAddr returns the remote network address.
18func (s *SessionUDP) RemoteAddr() net.Addr { return s.raddr }
19
20// setUDPSocketOptions sets the UDP socket options.
21// This function is implemented on a per platform basis. See udp_*.go for more details
22func setUDPSocketOptions(conn *net.UDPConn) error {
23	sa, err := getUDPSocketName(conn)
24	if err != nil {
25		return err
26	}
27	switch sa.(type) {
28	case *syscall.SockaddrInet6:
29		v6only, err := getUDPSocketOptions6Only(conn)
30		if err != nil {
31			return err
32		}
33		setUDPSocketOptions6(conn)
34		if !v6only {
35			setUDPSocketOptions4(conn)
36		}
37	case *syscall.SockaddrInet4:
38		setUDPSocketOptions4(conn)
39	}
40	return nil
41}
42
43// ReadFromSessionUDP acts just like net.UDPConn.ReadFrom(), but returns a session object instead of a
44// net.UDPAddr.
45func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error) {
46	oob := make([]byte, 40)
47	n, oobn, _, raddr, err := conn.ReadMsgUDP(b, oob)
48	if err != nil {
49		return n, nil, err
50	}
51	return n, &SessionUDP{raddr, oob[:oobn]}, err
52}
53
54// WriteToSessionUDP acts just like net.UDPConn.WritetTo(), but uses a *SessionUDP instead of a net.Addr.
55func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error) {
56	n, _, err := conn.WriteMsgUDP(b, session.context, session.raddr)
57	return n, err
58}
59