You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
1.3 KiB

  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. // +build !go1.9
  5. package socket
  6. import (
  7. "errors"
  8. "net"
  9. "os"
  10. "reflect"
  11. "runtime"
  12. )
  13. // A Conn represents a raw connection.
  14. type Conn struct {
  15. c net.Conn
  16. }
  17. // NewConn returns a new raw connection.
  18. func NewConn(c net.Conn) (*Conn, error) {
  19. return &Conn{c: c}, nil
  20. }
  21. func (o *Option) get(c *Conn, b []byte) (int, error) {
  22. s, err := socketOf(c.c)
  23. if err != nil {
  24. return 0, err
  25. }
  26. n, err := getsockopt(s, o.Level, o.Name, b)
  27. return n, os.NewSyscallError("getsockopt", err)
  28. }
  29. func (o *Option) set(c *Conn, b []byte) error {
  30. s, err := socketOf(c.c)
  31. if err != nil {
  32. return err
  33. }
  34. return os.NewSyscallError("setsockopt", setsockopt(s, o.Level, o.Name, b))
  35. }
  36. func socketOf(c net.Conn) (uintptr, error) {
  37. switch c.(type) {
  38. case *net.TCPConn, *net.UDPConn, *net.IPConn:
  39. v := reflect.ValueOf(c)
  40. switch e := v.Elem(); e.Kind() {
  41. case reflect.Struct:
  42. fd := e.FieldByName("conn").FieldByName("fd")
  43. switch e := fd.Elem(); e.Kind() {
  44. case reflect.Struct:
  45. sysfd := e.FieldByName("sysfd")
  46. if runtime.GOOS == "windows" {
  47. return uintptr(sysfd.Uint()), nil
  48. }
  49. return uintptr(sysfd.Int()), nil
  50. }
  51. }
  52. }
  53. return 0, errors.New("invalid type")
  54. }