Implement socket API

This commit is contained in:
Ilya Mizus
2013-11-05 00:07:43 +03:00
committed by Joshua Warner
parent 2800ffe826
commit 45ee25f68c
10 changed files with 623 additions and 56 deletions

View File

@ -0,0 +1,15 @@
/* 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.lang;
public interface AutoCloseable {
void close() throws Exception;
}

View File

@ -123,4 +123,7 @@ public class Throwable implements Serializable {
trace = trace(0);
return this;
}
public void addSuppressed(Throwable exception) {
}
}

View File

@ -13,41 +13,61 @@ package java.net;
import java.io.IOException;
public class InetAddress {
private final String address;
private final String name;
private final int ip;
private InetAddress(String address) {
this.address = address;
private InetAddress(String name) throws UnknownHostException {
this.name = name;
this.ip = ipv4AddressForName(name);
if (ip == 0) {
throw new UnknownHostException(name);
}
}
public String getHostName() {
return name;
}
public String getHostAddress() {
return address;
try {
return new InetAddress(name).toString();
} catch (UnknownHostException e) {
return null; // Strange case
}
}
public static InetAddress getByName(String name)
throws UnknownHostException
{
public static InetAddress getByName(String name) throws UnknownHostException {
try {
Socket.init();
return new InetAddress(name);
} catch (IOException e) {
UnknownHostException uhe = new UnknownHostException(name);
uhe.initCause(e);
throw uhe;
}
int address = ipv4AddressForName(name);
if (address == 0) {
throw new UnknownHostException(name);
} else {
return new InetAddress(ipv4AddressToString(address));
}
}
private static String ipv4AddressToString(int address) {
return (((address >>> 24) ) + "." +
((address >>> 16) & 0xFF) + "." +
((address >>> 8 ) & 0xFF) + "." +
((address ) & 0xFF));
public byte[] getAddress() {
byte[] res = new byte[4];
res[0] = (byte) ( ip >>> 24);
res[1] = (byte) ((ip >>> 16) & 0xFF);
res[2] = (byte) ((ip >>> 8 ) & 0xFF);
res[3] = (byte) ((ip ) & 0xFF);
return res;
}
private static native int ipv4AddressForName(String name);
@Override
public String toString() {
byte[] addr = getAddress();
return (int)((addr[0] + 256) % 256) + "." +
(int)((addr[1] + 256) % 256) + "." +
(int)((addr[2] + 256) % 256) + "." +
(int)((addr[3] + 256) % 256);
}
int getRawAddress() {
return ip;
}
static native int ipv4AddressForName(String name);
}

View File

@ -11,16 +11,25 @@
package java.net;
public class InetSocketAddress extends SocketAddress {
private final String host;
private final InetAddress address;
private final int port;
public InetSocketAddress(String host, int port) {
this.host = host;
public InetSocketAddress(String host, int port) throws UnknownHostException {
this.address = InetAddress.getByName(host);
this.port = port;
}
public InetSocketAddress(InetAddress address, int port) {
this.address = address;
this.port = port;
}
public InetAddress getAddress() {
return address;
}
public String getHostName() {
return host;
return address.getHostName();
}
public int getPort() {

View File

@ -10,10 +10,191 @@
package java.net;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public abstract class Socket {
public static native void init() throws IOException;
public class Socket implements Closeable, AutoCloseable {
public abstract void setTcpNoDelay(boolean on) throws SocketException;
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();
}
@Override
protected void finalize() throws Throwable {
close();
super.finalize();
}
}

View File

@ -50,7 +50,11 @@ public class SocketChannel extends SelectableChannel
}
public Socket socket() {
return new Handle();
try {
return new Handle();
} catch (IOException e) {
return null;
}
}
public boolean connect(SocketAddress address) throws IOException {
@ -165,7 +169,11 @@ public class SocketChannel extends SelectableChannel
}
public class Handle extends Socket {
public void setTcpNoDelay(boolean on) throws SocketException {
public Handle() throws IOException {
super();
}
public void setTcpNoDelay(boolean on) throws SocketException {
natSetTcpNoDelay(socket, on);
}
}