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 }