golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/internal/socket/rawconn.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package socket
     6  
     7  import (
     8  	"errors"
     9  	"net"
    10  	"os"
    11  	"syscall"
    12  )
    13  
    14  // A Conn represents a raw connection.
    15  type Conn struct {
    16  	network string
    17  	c       syscall.RawConn
    18  }
    19  
    20  // tcpConn is an interface implemented by net.TCPConn.
    21  // It can be used for interface assertions to check if a net.Conn is a TCP connection.
    22  type tcpConn interface {
    23  	SyscallConn() (syscall.RawConn, error)
    24  	SetLinger(int) error
    25  }
    26  
    27  var _ tcpConn = (*net.TCPConn)(nil)
    28  
    29  // udpConn is an interface implemented by net.UDPConn.
    30  // It can be used for interface assertions to check if a net.Conn is a UDP connection.
    31  type udpConn interface {
    32  	SyscallConn() (syscall.RawConn, error)
    33  	ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
    34  }
    35  
    36  var _ udpConn = (*net.UDPConn)(nil)
    37  
    38  // ipConn is an interface implemented by net.IPConn.
    39  // It can be used for interface assertions to check if a net.Conn is an IP connection.
    40  type ipConn interface {
    41  	SyscallConn() (syscall.RawConn, error)
    42  	ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *net.IPAddr, err error)
    43  }
    44  
    45  var _ ipConn = (*net.IPConn)(nil)
    46  
    47  // NewConn returns a new raw connection.
    48  func NewConn(c net.Conn) (*Conn, error) {
    49  	var err error
    50  	var cc Conn
    51  	switch c := c.(type) {
    52  	case tcpConn:
    53  		cc.network = "tcp"
    54  		cc.c, err = c.SyscallConn()
    55  	case udpConn:
    56  		cc.network = "udp"
    57  		cc.c, err = c.SyscallConn()
    58  	case ipConn:
    59  		cc.network = "ip"
    60  		cc.c, err = c.SyscallConn()
    61  	default:
    62  		return nil, errors.New("unknown connection type")
    63  	}
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	return &cc, nil
    68  }
    69  
    70  func (o *Option) get(c *Conn, b []byte) (int, error) {
    71  	var operr error
    72  	var n int
    73  	fn := func(s uintptr) {
    74  		n, operr = getsockopt(s, o.Level, o.Name, b)
    75  	}
    76  	if err := c.c.Control(fn); err != nil {
    77  		return 0, err
    78  	}
    79  	return n, os.NewSyscallError("getsockopt", operr)
    80  }
    81  
    82  func (o *Option) set(c *Conn, b []byte) error {
    83  	var operr error
    84  	fn := func(s uintptr) {
    85  		operr = setsockopt(s, o.Level, o.Name, b)
    86  	}
    87  	if err := c.c.Control(fn); err != nil {
    88  		return err
    89  	}
    90  	return os.NewSyscallError("setsockopt", operr)
    91  }