mirror of
https://github.com/corda/corda.git
synced 2025-01-09 06:23:04 +00:00
6e7149061c
The main idea is to make DatagramChannel and *SocketChannel behave in a way that more closely matches the standard, e.g. allow binding sockets to addresses without necessarily listening on those addresses and accept null addresses where appropriate. It also avoids multiple redundant DNS lookups. This commit also implements CharBuffer and BindException, and adds the Readable interface.
204 lines
5.0 KiB
Java
204 lines
5.0 KiB
Java
/* Copyright (c) 2008-2013, Avian Contributors
|
|
|
|
Permission to use, copy, modify, and/or distribute this software
|
|
for any purpose with or without fee is hereby granted, provided
|
|
that the above copyright notice and this permission notice appear
|
|
in all copies.
|
|
|
|
There is NO WARRANTY for this software. See license.txt for
|
|
details. */
|
|
|
|
package java.net;
|
|
|
|
import java.io.Closeable;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
|
|
public class Socket implements Closeable, AutoCloseable {
|
|
|
|
private static final int SD_RECEIVE = 0x00;
|
|
private static final int SD_SEND = 0x01;
|
|
private static final int SD_BOTH = 0x02;
|
|
|
|
private static final int BUFFER_SIZE = 65535;
|
|
|
|
/**
|
|
* This method is called from all routines that depend on winsock in windows,
|
|
* so it has public visibility
|
|
* @throws IOException
|
|
*/
|
|
public static native void init() throws IOException;
|
|
|
|
/**
|
|
* Creates the native socket object
|
|
* @return Handle to the native object
|
|
* @throws IOException
|
|
*/
|
|
private static native /* SOCKET */long create() throws IOException;
|
|
|
|
/**
|
|
* Connects the native socket object to an address:port
|
|
* @param sock Native socket handler
|
|
* @param addr Address to connect to
|
|
* @param port Port to connect to
|
|
* @throws IOException
|
|
*/
|
|
private static native void connect(/* SOCKET */long sock, long addr, short port) throws IOException;
|
|
private static native void bind(/* SOCKET */long sock, long addr, short port) throws IOException;
|
|
|
|
private static native void send(/* SOCKET */long sock, byte[] buffer, int start_pos, int count) throws IOException;
|
|
private static native int recv(/* SOCKET */long sock, byte[] buffer, int start_pos, int count) throws IOException;
|
|
|
|
private static native void abort(/* SOCKET */long sock);
|
|
private static native void close(/* SOCKET */long sock);
|
|
private static native void closeOutput(/* SOCKET */long sock);
|
|
private static native void closeInput(/* SOCKET */long sock);
|
|
|
|
private class SocketInputStream extends InputStream {
|
|
|
|
private boolean closed = false;
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
if (!closed) {
|
|
closeInput(sock);
|
|
closed = true;
|
|
}
|
|
super.close();
|
|
}
|
|
|
|
@Override
|
|
protected void finalize() throws Throwable {
|
|
close();
|
|
super.finalize();
|
|
}
|
|
|
|
@Override
|
|
public int read() throws IOException {
|
|
byte[] buffer = new byte[1];
|
|
int size = recv(sock, buffer, 0, 1);
|
|
if (size == 0) {
|
|
return -1;
|
|
}
|
|
return buffer[0];
|
|
}
|
|
|
|
@Override
|
|
public int read(byte[] buffer) throws IOException {
|
|
int fullSize = buffer.length;
|
|
int index = 0;
|
|
int size;
|
|
do {
|
|
size = recv(sock, buffer, index, Math.min(fullSize, Socket.BUFFER_SIZE));
|
|
fullSize -= size;
|
|
index += size;
|
|
} while (fullSize != 0 && size != 0);
|
|
return index;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
private class SocketOutputStream extends OutputStream {
|
|
|
|
private boolean closed = false;
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
if (!closed) {
|
|
closeOutput(sock);
|
|
closed = true;
|
|
}
|
|
super.close();
|
|
}
|
|
|
|
@Override
|
|
protected void finalize() throws Throwable {
|
|
close();
|
|
super.finalize();
|
|
}
|
|
|
|
@Override
|
|
public void write(int c) throws IOException {
|
|
byte[] res = new byte[1];
|
|
res[0] = (byte)c;
|
|
send(sock, res, 0, 1);
|
|
}
|
|
|
|
@Override
|
|
public void write(byte[] buffer) throws IOException {
|
|
int fullSize = buffer.length;
|
|
int index = 0;
|
|
int size;
|
|
do {
|
|
size = Math.min(fullSize, Socket.BUFFER_SIZE);
|
|
send(sock, buffer, index, size);
|
|
fullSize -= size;
|
|
index += size;
|
|
} while (fullSize != 0 && size != 0);
|
|
}
|
|
|
|
}
|
|
|
|
private long sock;
|
|
private SocketInputStream inputStream;
|
|
private SocketOutputStream outputStream;
|
|
|
|
public Socket() throws IOException {
|
|
Socket.init();
|
|
sock = create();
|
|
inputStream = new SocketInputStream();
|
|
outputStream = new SocketOutputStream();
|
|
}
|
|
|
|
public SocketInputStream getInputStream() {
|
|
return inputStream;
|
|
}
|
|
|
|
public SocketOutputStream getOutputStream() {
|
|
return outputStream;
|
|
}
|
|
|
|
public Socket(InetAddress address, int port) throws IOException {
|
|
this();
|
|
connect(sock, address.getRawAddress(), (short)port);
|
|
}
|
|
|
|
public Socket(String host, int port) throws UnknownHostException, IOException {
|
|
this(InetAddress.getByName(host), port);
|
|
}
|
|
|
|
public void bind(SocketAddress bindpoint) throws IOException {
|
|
if (bindpoint instanceof InetSocketAddress) {
|
|
InetSocketAddress inetBindpoint = (InetSocketAddress)bindpoint;
|
|
bind(sock, inetBindpoint.getAddress().getRawAddress(), (short) inetBindpoint.getPort());
|
|
}
|
|
}
|
|
|
|
public void setTcpNoDelay(boolean on) throws SocketException {}
|
|
|
|
@Override
|
|
public void close() throws IOException {
|
|
close(sock);
|
|
}
|
|
|
|
public void shutdownInput() throws IOException {
|
|
inputStream.close();
|
|
}
|
|
|
|
public void shutdownOutput() throws IOException {
|
|
outputStream.close();
|
|
}
|
|
|
|
public SocketAddress getRemoteSocketAddress() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
@Override
|
|
protected void finalize() throws Throwable {
|
|
close();
|
|
super.finalize();
|
|
}
|
|
}
|