/*
 * Copyright 2016 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package io.netty.channel.kqueue;

import io.netty.channel.DefaultFileRegion;
import io.netty.channel.unix.Errors;
import io.netty.channel.unix.PeerCredentials;
import io.netty.channel.unix.Socket;
import io.netty.util.internal.ThrowableUtil;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;

import static io.netty.channel.kqueue.AcceptFilter.PLATFORM_UNSUPPORTED;
import static io.netty.channel.unix.Errors.ERRNO_EPIPE_NEGATIVE;
import static io.netty.channel.unix.Errors.ioResult;
import static io.netty.channel.unix.Errors.newConnectionResetException;

A socket which provides access BSD native methods.
/** * A socket which provides access BSD native methods. */
final class BsdSocket extends Socket { private static final Errors.NativeIoException SENDFILE_CONNECTION_RESET_EXCEPTION; private static final ClosedChannelException SENDFILE_CLOSED_CHANNEL_EXCEPTION = ThrowableUtil.unknownStackTrace( new ClosedChannelException(), Native.class, "sendfile(..)"); // These limits are just based on observations. I couldn't find anything in header files which formally // define these limits. private static final int APPLE_SND_LOW_AT_MAX = 1 << 17; private static final int FREEBSD_SND_LOW_AT_MAX = 1 << 15; static final int BSD_SND_LOW_AT_MAX = Math.min(APPLE_SND_LOW_AT_MAX, FREEBSD_SND_LOW_AT_MAX); static { SENDFILE_CONNECTION_RESET_EXCEPTION = newConnectionResetException("syscall:sendfile", ERRNO_EPIPE_NEGATIVE); } BsdSocket(int fd) { super(fd); } void setAcceptFilter(AcceptFilter acceptFilter) throws IOException { setAcceptFilter(intValue(), acceptFilter.filterName(), acceptFilter.filterArgs()); } void setTcpNoPush(boolean tcpNoPush) throws IOException { setTcpNoPush(intValue(), tcpNoPush ? 1 : 0); } void setSndLowAt(int lowAt) throws IOException { setSndLowAt(intValue(), lowAt); } boolean isTcpNoPush() throws IOException { return getTcpNoPush(intValue()) != 0; } int getSndLowAt() throws IOException { return getSndLowAt(intValue()); } AcceptFilter getAcceptFilter() throws IOException { String[] result = getAcceptFilter(intValue()); return result == null ? PLATFORM_UNSUPPORTED : new AcceptFilter(result[0], result[1]); } PeerCredentials getPeerCredentials() throws IOException { return getPeerCredentials(intValue()); } long sendFile(DefaultFileRegion src, long baseOffset, long offset, long length) throws IOException { // Open the file-region as it may be created via the lazy constructor. This is needed as we directly access // the FileChannel field via JNI. src.open(); long res = sendFile(intValue(), src, baseOffset, offset, length); if (res >= 0) { return res; } return ioResult("sendfile", (int) res, SENDFILE_CONNECTION_RESET_EXCEPTION, SENDFILE_CLOSED_CHANNEL_EXCEPTION); } public static BsdSocket newSocketStream() { return new BsdSocket(newSocketStream0()); } public static BsdSocket newSocketDgram() { return new BsdSocket(newSocketDgram0()); } public static BsdSocket newSocketDomain() { return new BsdSocket(newSocketDomain0()); } private static native long sendFile(int socketFd, DefaultFileRegion src, long baseOffset, long offset, long length) throws IOException; private static native String[] getAcceptFilter(int fd) throws IOException; private static native int getTcpNoPush(int fd) throws IOException; private static native int getSndLowAt(int fd) throws IOException; private static native PeerCredentials getPeerCredentials(int fd) throws IOException; private static native void setAcceptFilter(int fd, String filterName, String filterArgs) throws IOException; private static native void setTcpNoPush(int fd, int tcpNoPush) throws IOException; private static native void setSndLowAt(int fd, int lowAt) throws IOException; }