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