1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.kqueue;
17
18 import io.netty.channel.DefaultFileRegion;
19 import io.netty.channel.socket.InternetProtocolFamily;
20 import io.netty.channel.socket.SocketProtocolFamily;
21 import io.netty.channel.unix.IovArray;
22 import io.netty.channel.unix.PeerCredentials;
23 import io.netty.channel.unix.Socket;
24
25 import java.io.IOException;
26 import java.net.Inet6Address;
27 import java.net.InetAddress;
28 import java.net.InetSocketAddress;
29
30 import static io.netty.channel.kqueue.AcceptFilter.PLATFORM_UNSUPPORTED;
31 import static io.netty.channel.kqueue.Native.CONNECT_TCP_FASTOPEN;
32 import static io.netty.channel.unix.Errors.ERRNO_EINPROGRESS_NEGATIVE;
33 import static io.netty.channel.unix.Errors.ioResult;
34 import static io.netty.channel.unix.NativeInetAddress.ipv4MappedIpv6Address;
35 import static io.netty.util.internal.ObjectUtil.checkNotNull;
36
37
38
39
40 final class BsdSocket extends Socket {
41
42
43
44 private static final int APPLE_SND_LOW_AT_MAX = 1 << 17;
45 private static final int FREEBSD_SND_LOW_AT_MAX = 1 << 15;
46 static final int BSD_SND_LOW_AT_MAX = Math.min(APPLE_SND_LOW_AT_MAX, FREEBSD_SND_LOW_AT_MAX);
47
48
49
50
51
52 private static final int UNSPECIFIED_SOURCE_INTERFACE = 0;
53
54 BsdSocket(int fd) {
55 super(fd);
56 }
57
58 void setAcceptFilter(AcceptFilter acceptFilter) throws IOException {
59 setAcceptFilter(intValue(), acceptFilter.filterName(), acceptFilter.filterArgs());
60 }
61
62 void setTcpNoPush(boolean tcpNoPush) throws IOException {
63 setTcpNoPush(intValue(), tcpNoPush ? 1 : 0);
64 }
65
66 void setSndLowAt(int lowAt) throws IOException {
67 setSndLowAt(intValue(), lowAt);
68 }
69
70 public void setTcpFastOpen(boolean enableTcpFastOpen) throws IOException {
71 setTcpFastOpen(intValue(), enableTcpFastOpen ? 1 : 0);
72 }
73
74 boolean isTcpNoPush() throws IOException {
75 return getTcpNoPush(intValue()) != 0;
76 }
77
78 int getSndLowAt() throws IOException {
79 return getSndLowAt(intValue());
80 }
81
82 AcceptFilter getAcceptFilter() throws IOException {
83 String[] result = getAcceptFilter(intValue());
84 return result == null ? PLATFORM_UNSUPPORTED : new AcceptFilter(result[0], result[1]);
85 }
86
87 public boolean isTcpFastOpen() throws IOException {
88 return isTcpFastOpen(intValue()) != 0;
89 }
90
91 PeerCredentials getPeerCredentials() throws IOException {
92 return getPeerCredentials(intValue());
93 }
94
95 long sendFile(DefaultFileRegion src, long baseOffset, long offset, long length) throws IOException {
96
97
98 src.open();
99
100 long res = sendFile(intValue(), src, baseOffset, offset, length);
101 if (res >= 0) {
102 return res;
103 }
104 return ioResult("sendfile", (int) res);
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 int connectx(InetSocketAddress source, InetSocketAddress destination, IovArray data, boolean tcpFastOpen)
123 throws IOException {
124 checkNotNull(destination, "Destination InetSocketAddress cannot be null.");
125 int flags = tcpFastOpen ? CONNECT_TCP_FASTOPEN : 0;
126
127 boolean sourceIPv6;
128 byte[] sourceAddress;
129 int sourceScopeId;
130 int sourcePort;
131 if (source == null) {
132 sourceIPv6 = false;
133 sourceAddress = null;
134 sourceScopeId = 0;
135 sourcePort = 0;
136 } else {
137 InetAddress sourceInetAddress = source.getAddress();
138 sourceIPv6 = useIpv6(this, sourceInetAddress);
139 if (sourceInetAddress instanceof Inet6Address) {
140 sourceAddress = sourceInetAddress.getAddress();
141 sourceScopeId = ((Inet6Address) sourceInetAddress).getScopeId();
142 } else {
143
144 sourceScopeId = 0;
145 sourceAddress = ipv4MappedIpv6Address(sourceInetAddress.getAddress());
146 }
147 sourcePort = source.getPort();
148 }
149
150 InetAddress destinationInetAddress = destination.getAddress();
151 boolean destinationIPv6 = useIpv6(this, destinationInetAddress);
152 byte[] destinationAddress;
153 int destinationScopeId;
154 if (destinationInetAddress instanceof Inet6Address) {
155 destinationAddress = destinationInetAddress.getAddress();
156 destinationScopeId = ((Inet6Address) destinationInetAddress).getScopeId();
157 } else {
158
159 destinationScopeId = 0;
160 destinationAddress = ipv4MappedIpv6Address(destinationInetAddress.getAddress());
161 }
162 int destinationPort = destination.getPort();
163
164 long iovAddress;
165 int iovCount;
166 int iovDataLength;
167 if (data == null || data.count() == 0) {
168 iovAddress = 0;
169 iovCount = 0;
170 iovDataLength = 0;
171 } else {
172 iovAddress = data.memoryAddress(0);
173 iovCount = data.count();
174 long size = data.size();
175 if (size > Integer.MAX_VALUE) {
176 throw new IOException("IovArray.size() too big: " + size + " bytes.");
177 }
178 iovDataLength = (int) size;
179 }
180
181 int result = connectx(intValue(),
182 UNSPECIFIED_SOURCE_INTERFACE, sourceIPv6, sourceAddress, sourceScopeId, sourcePort,
183 destinationIPv6, destinationAddress, destinationScopeId, destinationPort,
184 flags, iovAddress, iovCount, iovDataLength);
185 if (result == ERRNO_EINPROGRESS_NEGATIVE) {
186
187
188
189 return -iovDataLength;
190 }
191 if (result < 0) {
192 return ioResult("connectx", result);
193 }
194 return result;
195 }
196
197 public static BsdSocket newSocketStream() {
198 return new BsdSocket(newSocketStream0());
199 }
200
201
202
203
204 public static BsdSocket newSocketStream(InternetProtocolFamily protocol) {
205 return new BsdSocket(newSocketStream0(protocol));
206 }
207
208 public static BsdSocket newSocketStream(SocketProtocolFamily protocol) {
209 return new BsdSocket(newSocketStream0(protocol));
210 }
211
212 public static BsdSocket newSocketDgram() {
213 return new BsdSocket(newSocketDgram0());
214 }
215
216
217
218
219 public static BsdSocket newSocketDgram(InternetProtocolFamily protocol) {
220 return new BsdSocket(newSocketDgram0(protocol));
221 }
222
223 public static BsdSocket newSocketDgram(SocketProtocolFamily protocol) {
224 return new BsdSocket(newSocketDgram0(protocol));
225 }
226
227 public static BsdSocket newSocketDomain() {
228 return new BsdSocket(newSocketDomain0());
229 }
230
231 public static BsdSocket newSocketDomainDgram() {
232 return new BsdSocket(newSocketDomainDgram0());
233 }
234
235 private static native long sendFile(int socketFd, DefaultFileRegion src, long baseOffset,
236 long offset, long length) throws IOException;
237
238
239
240
241 private static native int connectx(
242 int socketFd,
243
244 int sourceInterface,
245 boolean sourceIPv6, byte[] sourceAddress, int sourceScopeId, int sourcePort,
246 boolean destinationIPv6, byte[] destinationAddress, int destinationScopeId, int destinationPort,
247
248 int flags,
249 long iovAddress, int iovCount, int iovDataLength
250
251 );
252
253 private static native String[] getAcceptFilter(int fd) throws IOException;
254
255 private static native int getTcpNoPush(int fd) throws IOException;
256
257 private static native int getSndLowAt(int fd) throws IOException;
258
259 private static native int isTcpFastOpen(int fd) throws IOException;
260
261 private static native PeerCredentials getPeerCredentials(int fd) throws IOException;
262
263 private static native void setAcceptFilter(int fd, String filterName, String filterArgs) throws IOException;
264
265 private static native void setTcpNoPush(int fd, int tcpNoPush) throws IOException;
266
267 private static native void setSndLowAt(int fd, int lowAt) throws IOException;
268
269 private static native void setTcpFastOpen(int fd, int enableFastOpen) throws IOException;
270 }