View Javadoc
1   /*
2    * Copyright 2016 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel.kqueue;
17  
18  import io.netty.channel.DefaultFileRegion;
19  import io.netty.channel.unix.Errors;
20  import io.netty.channel.unix.PeerCredentials;
21  import io.netty.channel.unix.Socket;
22  import io.netty.util.internal.ThrowableUtil;
23  
24  import java.io.IOException;
25  import java.nio.channels.ClosedChannelException;
26  
27  import static io.netty.channel.kqueue.AcceptFilter.PLATFORM_UNSUPPORTED;
28  import static io.netty.channel.unix.Errors.ERRNO_EPIPE_NEGATIVE;
29  import static io.netty.channel.unix.Errors.ioResult;
30  import static io.netty.channel.unix.Errors.newConnectionResetException;
31  
32  /**
33   * A socket which provides access BSD native methods.
34   */
35  final class BsdSocket extends Socket {
36      private static final Errors.NativeIoException SENDFILE_CONNECTION_RESET_EXCEPTION;
37      private static final ClosedChannelException SENDFILE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace(
38              new ClosedChannelException(), Native.class, "sendfile(..)");
39  
40      // These limits are just based on observations. I couldn't find anything in header files which formally
41      // define these limits.
42      private static final int APPLE_SND_LOW_AT_MAX = 1 << 17;
43      private static final int FREEBSD_SND_LOW_AT_MAX = 1 << 15;
44      static final int BSD_SND_LOW_AT_MAX = Math.min(APPLE_SND_LOW_AT_MAX, FREEBSD_SND_LOW_AT_MAX);
45  
46      static {
47          SENDFILE_CONNECTION_RESET_EXCEPTION = newConnectionResetException("syscall:sendfile",
48                  ERRNO_EPIPE_NEGATIVE);
49      }
50  
51      BsdSocket(int fd) {
52          super(fd);
53      }
54  
55      void setAcceptFilter(AcceptFilter acceptFilter) throws IOException {
56          setAcceptFilter(intValue(), acceptFilter.filterName(), acceptFilter.filterArgs());
57      }
58  
59      void setTcpNoPush(boolean tcpNoPush) throws IOException {
60          setTcpNoPush(intValue(), tcpNoPush ? 1 : 0);
61      }
62  
63      void setSndLowAt(int lowAt) throws IOException {
64          setSndLowAt(intValue(), lowAt);
65      }
66  
67      boolean isTcpNoPush() throws IOException  {
68          return getTcpNoPush(intValue()) != 0;
69      }
70  
71      int getSndLowAt() throws IOException {
72          return getSndLowAt(intValue());
73      }
74  
75      AcceptFilter getAcceptFilter() throws IOException {
76          String[] result = getAcceptFilter(intValue());
77          return result == null ? PLATFORM_UNSUPPORTED : new AcceptFilter(result[0], result[1]);
78      }
79  
80      PeerCredentials getPeerCredentials() throws IOException {
81          return getPeerCredentials(intValue());
82      }
83  
84      long sendFile(DefaultFileRegion src, long baseOffset, long offset, long length) throws IOException {
85          // Open the file-region as it may be created via the lazy constructor. This is needed as we directly access
86          // the FileChannel field via JNI.
87          src.open();
88  
89          long res = sendFile(intValue(), src, baseOffset, offset, length);
90          if (res >= 0) {
91              return res;
92          }
93          return ioResult("sendfile", (int) res, SENDFILE_CONNECTION_RESET_EXCEPTION, SENDFILE_CLOSED_CHANNEL_EXCEPTION);
94      }
95  
96      public static BsdSocket newSocketStream() {
97          return new BsdSocket(newSocketStream0());
98      }
99  
100     public static BsdSocket newSocketDgram() {
101         return new BsdSocket(newSocketDgram0());
102     }
103 
104     public static BsdSocket newSocketDomain() {
105         return new BsdSocket(newSocketDomain0());
106     }
107 
108     private static native long sendFile(int socketFd, DefaultFileRegion src, long baseOffset,
109                                         long offset, long length) throws IOException;
110 
111     private static native String[] getAcceptFilter(int fd) throws IOException;
112     private static native int getTcpNoPush(int fd) throws IOException;
113     private static native int getSndLowAt(int fd) throws IOException;
114     private static native PeerCredentials getPeerCredentials(int fd) throws IOException;
115 
116     private static native void setAcceptFilter(int fd, String filterName, String filterArgs) throws IOException;
117     private static native void setTcpNoPush(int fd, int tcpNoPush) throws IOException;
118     private static native void setSndLowAt(int fd, int lowAt) throws IOException;
119 }