rawconn.go raw

   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  }
  92