rawconn.go 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. package socket
  5. import (
  6. "errors"
  7. "net"
  8. "os"
  9. "syscall"
  10. )
  11. // A Conn represents a raw connection.
  12. type Conn struct {
  13. network string
  14. c syscall.RawConn
  15. }
  16. // tcpConn is an interface implemented by net.TCPConn.
  17. // It can be used for interface assertions to check if a net.Conn is a TCP connection.
  18. type tcpConn interface {
  19. SyscallConn() (syscall.RawConn, error)
  20. SetLinger(int) error
  21. }
  22. var _ tcpConn = (*net.TCPConn)(nil)
  23. // udpConn is an interface implemented by net.UDPConn.
  24. // It can be used for interface assertions to check if a net.Conn is a UDP connection.
  25. type udpConn interface {
  26. SyscallConn() (syscall.RawConn, error)
  27. ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
  28. }
  29. var _ udpConn = (*net.UDPConn)(nil)
  30. // ipConn is an interface implemented by net.IPConn.
  31. // It can be used for interface assertions to check if a net.Conn is an IP connection.
  32. type ipConn interface {
  33. SyscallConn() (syscall.RawConn, error)
  34. ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *net.IPAddr, err error)
  35. }
  36. var _ ipConn = (*net.IPConn)(nil)
  37. // NewConn returns a new raw connection.
  38. func NewConn(c net.Conn) (*Conn, error) {
  39. var err error
  40. var cc Conn
  41. switch c := c.(type) {
  42. case tcpConn:
  43. cc.network = "tcp"
  44. cc.c, err = c.SyscallConn()
  45. case udpConn:
  46. cc.network = "udp"
  47. cc.c, err = c.SyscallConn()
  48. case ipConn:
  49. cc.network = "ip"
  50. cc.c, err = c.SyscallConn()
  51. default:
  52. return nil, errors.New("unknown connection type")
  53. }
  54. if err != nil {
  55. return nil, err
  56. }
  57. return &cc, nil
  58. }
  59. func (o *Option) get(c *Conn, b []byte) (int, error) {
  60. var operr error
  61. var n int
  62. fn := func(s uintptr) {
  63. n, operr = getsockopt(s, o.Level, o.Name, b)
  64. }
  65. if err := c.c.Control(fn); err != nil {
  66. return 0, err
  67. }
  68. return n, os.NewSyscallError("getsockopt", operr)
  69. }
  70. func (o *Option) set(c *Conn, b []byte) error {
  71. var operr error
  72. fn := func(s uintptr) {
  73. operr = setsockopt(s, o.Level, o.Name, b)
  74. }
  75. if err := c.c.Control(fn); err != nil {
  76. return err
  77. }
  78. return os.NewSyscallError("setsockopt", operr)
  79. }