/*
* Copyright 2015 Odnoklassniki Ltd, Mail.Ru Group
*
* Licensed 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 one.nio.net;
import one.nio.os.Mem;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
class NativeSocket extends Socket {
int fd;
NativeSocket() throws IOException {
this.fd = socket0();
}
NativeSocket(int fd) {
this.fd = fd;
}
@Override
public final boolean isOpen() {
return fd >= 0;
}
@Override
public NativeSocket accept() throws IOException {
return new NativeSocket(accept0());
}
@Override
public final InetSocketAddress getLocalAddress() {
byte[] buffer = new byte[24];
return makeAddress(buffer, getsockname(buffer));
}
@Override
public final InetSocketAddress getRemoteAddress() {
byte[] buffer = new byte[24];
return makeAddress(buffer, getpeername(buffer));
}
private InetSocketAddress makeAddress(byte[] buffer, int length) {
byte[] address;
if (length == 8) {
address = new byte[4];
System.arraycopy(buffer, 4, address, 0, 4);
} else if (length == 24) {
address = new byte[16];
System.arraycopy(buffer, 8, address, 0, 16);
} else {
return null;
}
int port = (buffer[2] & 0xff) << 8 | (buffer[3] & 0xff);
try {
return new InetSocketAddress(InetAddress.getByAddress(address), port);
} catch (UnknownHostException e) {
return null;
}
}
@Override
public final Socket ssl(SslContext context) throws IOException {
return new NativeSslSocket(fd, (NativeSslContext) context, false);
}
@Override
public SslContext getSslContext() {
return null;
}
@Override
public final void connect(InetAddress address, int port) throws IOException {
connect0(address.getAddress(), port);
}
@Override
public final void bind(InetAddress address, int port, int backlog) throws IOException {
bind0(address.getAddress(), port, backlog);
}
@Override
public native void close();
@Override
public native int writeRaw(long buf, int count, int flags) throws IOException;
@Override
public native int write(byte[] data, int offset, int count, int flags) throws IOException;
@Override
public native void writeFully(byte[] data, int offset, int count) throws IOException;
@Override
public native int readRaw(long buf, int count, int flags) throws IOException;
@Override
public native int read(byte[] data, int offset, int count) throws IOException;
@Override
public native void readFully(byte[] data, int offset, int count) throws IOException;
@Override
public long sendFile(RandomAccessFile file, long offset, long count) throws IOException {
return sendFile0(Mem.getFD(file.getFD()), offset, count);
}
@Override
public final native void setBlocking(boolean blocking);
@Override
public final native void setTimeout(int timeout);
@Override
public final native void setKeepAlive(boolean keepAlive);
@Override
public final native void setNoDelay(boolean noDelay);
@Override
public final native void setDeferAccept(boolean deferAccept);
@Override
public final native void setReuseAddr(boolean reuseAddr);
@Override
public final native void setRecvBuffer(int recvBuf);
@Override
public final native void setSendBuffer(int sendBuf);
@Override
public final native byte[] getOption(int level, int option);
@Override
public final native boolean setOption(int level, int option, byte[] value);
static native int socket0() throws IOException;
native int accept0() throws IOException;
native void connect0(byte[] address, int port) throws IOException;
native void bind0(byte[] address, int port, int backlog) throws IOException;
native long sendFile0(int sourceFD, long offset, long count) throws IOException;
native int getsockname(byte[] buffer);
native int getpeername(byte[] buffer);
}