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 SocketProtocolFamily family() {
59 return ipv6 ? SocketProtocolFamily.INET6 : SocketProtocolFamily.INET;
60 }
61
62 void setAcceptFilter(AcceptFilter acceptFilter) throws IOException {
63 setAcceptFilter(intValue(), acceptFilter.filterName(), acceptFilter.filterArgs());
64 }
65
66 void setTcpNoPush(boolean tcpNoPush) throws IOException {
67 setTcpNoPush(intValue(), tcpNoPush ? 1 : 0);
68 }
69
70 void setSndLowAt(int lowAt) throws IOException {
71 setSndLowAt(intValue(), lowAt);
72 }
73
74 public void setTcpFastOpen(boolean enableTcpFastOpen) throws IOException {
75 setTcpFastOpen(intValue(), enableTcpFastOpen ? 1 : 0);
76 }
77
78 boolean isTcpNoPush() throws IOException {
79 return getTcpNoPush(intValue()) != 0;
80 }
81
82 int getSndLowAt() throws IOException {
83 return getSndLowAt(intValue());
84 }
85
86 AcceptFilter getAcceptFilter() throws IOException {
87 String[] result = getAcceptFilter(intValue());
88 return result == null ? PLATFORM_UNSUPPORTED : new AcceptFilter(result[0], result[1]);
89 }
90
91 public boolean isTcpFastOpen() throws IOException {
92 return isTcpFastOpen(intValue()) != 0;
93 }
94
95 PeerCredentials getPeerCredentials() throws IOException {
96 return getPeerCredentials(intValue());
97 }
98
99 long sendFile(DefaultFileRegion src, long baseOffset, long offset, long length) throws IOException {
100
101
102 src.open();
103
104 long res = sendFile(intValue(), src, baseOffset, offset, length);
105 if (res >= 0) {
106 return res;
107 }
108 return ioResult("sendfile", (int) res);
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 int connectx(InetSocketAddress source, InetSocketAddress destination, IovArray data, boolean tcpFastOpen)
127 throws IOException {
128 checkNotNull(destination, "Destination InetSocketAddress cannot be null.");
129 int flags = tcpFastOpen ? CONNECT_TCP_FASTOPEN : 0;
130
131 boolean sourceIPv6;
132 byte[] sourceAddress;
133 int sourceScopeId;
134 int sourcePort;
135 if (source == null) {
136 sourceIPv6 = false;
137 sourceAddress = null;
138 sourceScopeId = 0;
139 sourcePort = 0;
140 } else {
141 InetAddress sourceInetAddress = source.getAddress();
142 sourceIPv6 = useIpv6(this, sourceInetAddress);
143 if (sourceInetAddress instanceof Inet6Address) {
144 sourceAddress = sourceInetAddress.getAddress();
145 sourceScopeId = ((Inet6Address) sourceInetAddress).getScopeId();
146 } else {
147
148 sourceScopeId = 0;
149 sourceAddress = ipv4MappedIpv6Address(sourceInetAddress.getAddress());
150 }
151 sourcePort = source.getPort();
152 }
153
154 InetAddress destinationInetAddress = destination.getAddress();
155 boolean destinationIPv6 = useIpv6(this, destinationInetAddress);
156 byte[] destinationAddress;
157 int destinationScopeId;
158 if (destinationInetAddress instanceof Inet6Address) {
159 destinationAddress = destinationInetAddress.getAddress();
160 destinationScopeId = ((Inet6Address) destinationInetAddress).getScopeId();
161 } else {
162
163 destinationScopeId = 0;
164 destinationAddress = ipv4MappedIpv6Address(destinationInetAddress.getAddress());
165 }
166 int destinationPort = destination.getPort();
167
168 long iovAddress;
169 int iovCount;
170 int iovDataLength;
171 if (data == null || data.count() == 0) {
172 iovAddress = 0;
173 iovCount = 0;
174 iovDataLength = 0;
175 } else {
176 iovAddress = data.memoryAddress(0);
177 iovCount = data.count();
178 long size = data.size();
179 if (size > Integer.MAX_VALUE) {
180 throw new IOException("IovArray.size() too big: " + size + " bytes.");
181 }
182 iovDataLength = (int) size;
183 }
184
185 int result = connectx(intValue(),
186 UNSPECIFIED_SOURCE_INTERFACE, sourceIPv6, sourceAddress, sourceScopeId, sourcePort,
187 destinationIPv6, destinationAddress, destinationScopeId, destinationPort,
188 flags, iovAddress, iovCount, iovDataLength);
189 if (result == ERRNO_EINPROGRESS_NEGATIVE) {
190
191
192
193 return -iovDataLength;
194 }
195 if (result < 0) {
196 return ioResult("connectx", result);
197 }
198 return result;
199 }
200
201 public static BsdSocket newSocketStream() {
202 return new BsdSocket(newSocketStream0());
203 }
204
205
206
207
208 public static BsdSocket newSocketStream(InternetProtocolFamily protocol) {
209 return new BsdSocket(newSocketStream0(protocol));
210 }
211
212 public static BsdSocket newSocketStream(SocketProtocolFamily protocol) {
213 return new BsdSocket(newSocketStream0(protocol));
214 }
215
216 public static BsdSocket newSocketDgram() {
217 return new BsdSocket(newSocketDgram0());
218 }
219
220
221
222
223 public static BsdSocket newSocketDgram(InternetProtocolFamily protocol) {
224 return new BsdSocket(newSocketDgram0(protocol));
225 }
226
227 public static BsdSocket newSocketDgram(SocketProtocolFamily protocol) {
228 return new BsdSocket(newSocketDgram0(protocol));
229 }
230
231 public static BsdSocket newSocketDomain() {
232 return new BsdSocket(newSocketDomain0());
233 }
234
235 public static BsdSocket newSocketDomainDgram() {
236 return new BsdSocket(newSocketDomainDgram0());
237 }
238
239 private static native long sendFile(int socketFd, DefaultFileRegion src, long baseOffset,
240 long offset, long length) throws IOException;
241
242
243
244
245 private static native int connectx(
246 int socketFd,
247
248 int sourceInterface,
249 boolean sourceIPv6, byte[] sourceAddress, int sourceScopeId, int sourcePort,
250 boolean destinationIPv6, byte[] destinationAddress, int destinationScopeId, int destinationPort,
251
252 int flags,
253 long iovAddress, int iovCount, int iovDataLength
254
255 );
256
257 private static native String[] getAcceptFilter(int fd) throws IOException;
258
259 private static native int getTcpNoPush(int fd) throws IOException;
260
261 private static native int getSndLowAt(int fd) throws IOException;
262
263 private static native int isTcpFastOpen(int fd) throws IOException;
264
265 private static native PeerCredentials getPeerCredentials(int fd) throws IOException;
266
267 private static native void setAcceptFilter(int fd, String filterName, String filterArgs) throws IOException;
268
269 private static native void setTcpNoPush(int fd, int tcpNoPush) throws IOException;
270
271 private static native void setSndLowAt(int fd, int lowAt) throws IOException;
272
273 private static native void setTcpFastOpen(int fd, int enableFastOpen) throws IOException;
274 }