forked from v2fly/v2ray-core
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsockopt_darwin.go
141 lines (124 loc) · 4.74 KB
/
sockopt_darwin.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package internet
import (
"net"
"golang.org/x/sys/unix"
)
const (
// TCP_FASTOPEN_SERVER is the value to enable TCP fast open on darwin for server connections.
TCP_FASTOPEN_SERVER = 0x01 // nolint: revive,stylecheck
// TCP_FASTOPEN_CLIENT is the value to enable TCP fast open on darwin for client connections.
TCP_FASTOPEN_CLIENT = 0x02 // nolint: revive,stylecheck
)
func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
if isTCPSocket(network) {
switch config.Tfo {
case SocketConfig_Enable:
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, TCP_FASTOPEN_CLIENT); err != nil {
return err
}
case SocketConfig_Disable:
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 0); err != nil {
return err
}
}
if config.TcpKeepAliveInterval > 0 {
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
return newError("failed to set TCP_KEEPINTVL").Base(err)
}
}
if config.TcpKeepAliveIdle > 0 {
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, int(config.TcpKeepAliveIdle)); err != nil {
return newError("failed to set TCP_KEEPALIVE (TCP keepalive idle time on Darwin)").Base(err)
}
}
if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil {
return newError("failed to set SO_KEEPALIVE").Base(err)
}
}
}
if config.BindToDevice != "" {
iface, err := net.InterfaceByName(config.BindToDevice)
if err != nil {
return newError("failed to get interface ", config.BindToDevice).Base(err)
}
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index); err != nil {
return newError("failed to set IP_BOUND_IF", err)
}
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, iface.Index); err != nil {
return newError("failed to set IPV6_BOUND_IF", err)
}
}
if config.TxBufSize != 0 {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, int(config.TxBufSize)); err != nil {
return newError("failed to set SO_SNDBUF").Base(err)
}
}
if config.RxBufSize != 0 {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, int(config.RxBufSize)); err != nil {
return newError("failed to set SO_RCVBUF").Base(err)
}
}
return nil
}
func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
if isTCPSocket(network) {
switch config.Tfo {
case SocketConfig_Enable:
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, TCP_FASTOPEN_SERVER); err != nil {
return err
}
case SocketConfig_Disable:
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_FASTOPEN, 0); err != nil {
return err
}
}
if config.TcpKeepAliveInterval > 0 {
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
return newError("failed to set TCP_KEEPINTVL").Base(err)
}
}
if config.TcpKeepAliveIdle > 0 {
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, int(config.TcpKeepAliveIdle)); err != nil {
return newError("failed to set TCP_KEEPALIVE (TCP keepalive idle time on Darwin)").Base(err)
}
}
if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil {
return newError("failed to set SO_KEEPALIVE").Base(err)
}
}
}
if config.BindToDevice != "" {
iface, err := net.InterfaceByName(config.BindToDevice)
if err != nil {
return newError("failed to get interface ", config.BindToDevice).Base(err)
}
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, iface.Index); err != nil {
return newError("failed to set IP_BOUND_IF", err)
}
if err := unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, iface.Index); err != nil {
return newError("failed to set IPV6_BOUND_IF", err)
}
}
if config.TxBufSize != 0 {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_SNDBUF, int(config.TxBufSize)); err != nil {
return newError("failed to set SO_SNDBUF/SO_SNDBUFFORCE").Base(err)
}
}
if config.RxBufSize != 0 {
if err := unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_RCVBUF, int(config.RxBufSize)); err != nil {
return newError("failed to set SO_RCVBUF/SO_RCVBUFFORCE").Base(err)
}
}
return nil
}
func bindAddr(fd uintptr, address []byte, port uint32) error {
return nil
}
func setReuseAddr(fd uintptr) error {
return nil
}
func setReusePort(fd uintptr) error {
return nil
}