blob: 87e81071c1049ac637e610b82cef55bfae741b25 [file] [log] [blame]
Mikio Hara50e760f2017-02-15 06:52:17 +09001// 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
Mikio Hara50e760f2017-02-15 06:52:17 +09005package socket
6
7import (
8 "errors"
9 "net"
10 "os"
11 "syscall"
12)
13
14// A Conn represents a raw connection.
15type Conn struct {
16 network string
17 c syscall.RawConn
18}
19
Marten Seemanna5a99cb2020-11-23 15:42:45 +070020// 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.
22type tcpConn interface {
23 SyscallConn() (syscall.RawConn, error)
24 SetLinger(int) error
25}
26
27var _ 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.
31type udpConn interface {
32 SyscallConn() (syscall.RawConn, error)
33 ReadMsgUDP(b, oob []byte) (n, oobn, flags int, addr *net.UDPAddr, err error)
34}
35
36var _ 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.
40type ipConn interface {
41 SyscallConn() (syscall.RawConn, error)
42 ReadMsgIP(b, oob []byte) (n, oobn, flags int, addr *net.IPAddr, err error)
43}
44
45var _ ipConn = (*net.IPConn)(nil)
46
Mikio Hara50e760f2017-02-15 06:52:17 +090047// NewConn returns a new raw connection.
48func NewConn(c net.Conn) (*Conn, error) {
49 var err error
50 var cc Conn
51 switch c := c.(type) {
Marten Seemanna5a99cb2020-11-23 15:42:45 +070052 case tcpConn:
Mikio Hara50e760f2017-02-15 06:52:17 +090053 cc.network = "tcp"
54 cc.c, err = c.SyscallConn()
Marten Seemanna5a99cb2020-11-23 15:42:45 +070055 case udpConn:
Mikio Hara50e760f2017-02-15 06:52:17 +090056 cc.network = "udp"
57 cc.c, err = c.SyscallConn()
Marten Seemanna5a99cb2020-11-23 15:42:45 +070058 case ipConn:
Mikio Hara50e760f2017-02-15 06:52:17 +090059 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
70func (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
82func (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}