mirror of
https://github.com/corda/corda.git
synced 2025-02-01 16:58:27 +00:00
Merge pull request #212 from dicej/net
various refinements to network implementation
This commit is contained in:
commit
573367e7a1
@ -149,46 +149,12 @@ throwSocketException(JNIEnv* e)
|
|||||||
throwSocketException(e, errorString(e));
|
throwSocketException(e, errorString(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void init(sockaddr_in* address, jint host, jint port)
|
||||||
init(JNIEnv* e, sockaddr_in* address, jstring hostString, jint port)
|
|
||||||
{
|
{
|
||||||
const char* chars = e->GetStringUTFChars(hostString, 0);
|
memset(address, 0, sizeof(sockaddr_in));
|
||||||
if (chars) {
|
address->sin_family = AF_INET;
|
||||||
#ifdef PLATFORM_WINDOWS
|
address->sin_port = htons(port);
|
||||||
hostent* host = gethostbyname(chars);
|
address->sin_addr.s_addr = htonl(host);
|
||||||
e->ReleaseStringUTFChars(hostString, chars);
|
|
||||||
if (host == 0) {
|
|
||||||
throwIOException(e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(address, 0, sizeof(sockaddr_in));
|
|
||||||
address->sin_family = AF_INET;
|
|
||||||
address->sin_port = htons(port);
|
|
||||||
address->sin_addr = *reinterpret_cast<in_addr*>(host->h_addr_list[0]);
|
|
||||||
#else
|
|
||||||
addrinfo hints;
|
|
||||||
memset(&hints, 0, sizeof(addrinfo));
|
|
||||||
hints.ai_family = AF_INET;
|
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
|
|
||||||
addrinfo* result;
|
|
||||||
int r = getaddrinfo(chars, 0, &hints, &result);
|
|
||||||
e->ReleaseStringUTFChars(hostString, chars);
|
|
||||||
if (r != 0) {
|
|
||||||
throwIOException(e, gai_strerror(r));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(address, 0, sizeof(sockaddr_in));
|
|
||||||
address->sin_family = AF_INET;
|
|
||||||
address->sin_port = htons(port);
|
|
||||||
address->sin_addr = reinterpret_cast<sockaddr_in*>
|
|
||||||
(result->ai_addr)->sin_addr;
|
|
||||||
|
|
||||||
freeaddrinfo(result);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
@ -384,8 +350,17 @@ doWrite(int fd, const void* buffer, size_t count)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int doSend(int fd, sockaddr_in* address, const void* buffer, size_t count)
|
||||||
makeSocket(JNIEnv* e, int type = SOCK_STREAM, int protocol = IPPROTO_TCP)
|
{
|
||||||
|
return sendto(fd,
|
||||||
|
static_cast<const char*>(buffer),
|
||||||
|
count,
|
||||||
|
0,
|
||||||
|
reinterpret_cast<sockaddr*>(address),
|
||||||
|
sizeof(sockaddr_in));
|
||||||
|
}
|
||||||
|
|
||||||
|
int makeSocket(JNIEnv* e, int type = SOCK_STREAM, int protocol = IPPROTO_TCP)
|
||||||
{
|
{
|
||||||
int s = ::socket(AF_INET, type, protocol);
|
int s = ::socket(AF_INET, type, protocol);
|
||||||
if (s < 0) {
|
if (s < 0) {
|
||||||
@ -405,43 +380,44 @@ Java_java_nio_channels_ServerSocketChannel_natDoAccept(JNIEnv *e, jclass, jint s
|
|||||||
return ::doAccept(e, socket);
|
return ::doAccept(e, socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_ServerSocketChannel_natDoListen(JNIEnv *e,
|
Java_java_nio_channels_ServerSocketChannel_natDoListen(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jstring host,
|
jint socket,
|
||||||
jint port)
|
jint host,
|
||||||
|
jint port)
|
||||||
{
|
{
|
||||||
int s = makeSocket(e);
|
|
||||||
if (s < 0) return s;
|
|
||||||
if (e->ExceptionCheck()) return 0;
|
|
||||||
|
|
||||||
sockaddr_in address;
|
sockaddr_in address;
|
||||||
init(e, &address, host, port);
|
init(&address, host, port);
|
||||||
if (e->ExceptionCheck()) return 0;
|
|
||||||
|
|
||||||
::doBind(e, s, &address);
|
::doBind(e, socket, &address);
|
||||||
if (e->ExceptionCheck()) return 0;
|
if (e->ExceptionCheck())
|
||||||
|
return;
|
||||||
|
|
||||||
::doListen(e, s);
|
::doListen(e, socket);
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_DatagramChannel_bind(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_bind(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jstring host,
|
jint socket,
|
||||||
jint port)
|
jint host,
|
||||||
|
jint port)
|
||||||
{
|
{
|
||||||
int s = makeSocket(e, SOCK_DGRAM, IPPROTO_UDP);
|
|
||||||
if (s < 0) return s;
|
|
||||||
if (e->ExceptionCheck()) return 0;
|
|
||||||
|
|
||||||
sockaddr_in address;
|
sockaddr_in address;
|
||||||
init(e, &address, host, port);
|
init(&address, host, port);
|
||||||
if (e->ExceptionCheck()) return 0;
|
|
||||||
|
|
||||||
::doBind(e, s, &address);
|
::doBind(e, socket, &address);
|
||||||
return s;
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_java_nio_channels_DatagramChannel_bind(JNIEnv* e,
|
||||||
|
jclass c,
|
||||||
|
jint socket,
|
||||||
|
jint host,
|
||||||
|
jint port)
|
||||||
|
{
|
||||||
|
Java_java_nio_channels_SocketChannel_bind(e, c, socket, host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
@ -472,45 +448,42 @@ Java_java_nio_channels_SocketChannel_natSetTcpNoDelay(JNIEnv *e,
|
|||||||
setTcpNoDelay(e, socket, on);
|
setTcpNoDelay(e, socket, on);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
Java_java_nio_channels_SocketChannel_natDoConnect(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_natDoConnect(JNIEnv* e,
|
||||||
jclass,
|
jclass,
|
||||||
jstring host,
|
jint socket,
|
||||||
jint port,
|
jint host,
|
||||||
jboolean blocking,
|
jint port)
|
||||||
jbooleanArray retVal)
|
|
||||||
{
|
{
|
||||||
int s = makeSocket(e);
|
|
||||||
if (e->ExceptionCheck()) return 0;
|
|
||||||
|
|
||||||
setBlocking(e, s, blocking);
|
|
||||||
|
|
||||||
sockaddr_in address;
|
sockaddr_in address;
|
||||||
init(e, &address, host, port);
|
init(&address, host, port);
|
||||||
if (e->ExceptionCheck()) return 0;
|
|
||||||
|
|
||||||
jboolean connected = ::doConnect(e, s, &address);
|
return ::doConnect(e, socket, &address);
|
||||||
e->SetBooleanArrayRegion(retVal, 0, 1, &connected);
|
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT jint JNICALL
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
Java_java_nio_channels_DatagramChannel_connect(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_makeSocket(JNIEnv* e, jclass)
|
||||||
jclass,
|
|
||||||
jstring host,
|
|
||||||
jint port)
|
|
||||||
{
|
{
|
||||||
int s = makeSocket(e, SOCK_DGRAM, IPPROTO_UDP);
|
return makeSocket(e);
|
||||||
if (e->ExceptionCheck()) return 0;
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
|
Java_java_nio_channels_DatagramChannel_makeSocket(JNIEnv* e, jclass)
|
||||||
|
{
|
||||||
|
return makeSocket(e, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jboolean JNICALL
|
||||||
|
Java_java_nio_channels_DatagramChannel_connect(JNIEnv* e,
|
||||||
|
jclass,
|
||||||
|
jint socket,
|
||||||
|
jint host,
|
||||||
|
jint port)
|
||||||
|
{
|
||||||
sockaddr_in address;
|
sockaddr_in address;
|
||||||
init(e, &address, host, port);
|
init(&address, host, port);
|
||||||
if (e->ExceptionCheck()) return 0;
|
|
||||||
|
|
||||||
::doConnect(e, s, &address);
|
return ::doConnect(e, socket, &address);
|
||||||
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
@ -669,6 +642,51 @@ Java_java_nio_channels_DatagramChannel_write(JNIEnv* e,
|
|||||||
(e, c, socket, buffer, offset, length, blocking);
|
(e, c, socket, buffer, offset, length, blocking);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT jint JNICALL
|
||||||
|
Java_java_nio_channels_DatagramChannel_send(JNIEnv* e,
|
||||||
|
jclass,
|
||||||
|
jint socket,
|
||||||
|
jint host,
|
||||||
|
jint port,
|
||||||
|
jbyteArray buffer,
|
||||||
|
jint offset,
|
||||||
|
jint length,
|
||||||
|
jboolean blocking)
|
||||||
|
{
|
||||||
|
sockaddr_in address;
|
||||||
|
init(&address, host, port);
|
||||||
|
|
||||||
|
int r;
|
||||||
|
if (blocking) {
|
||||||
|
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||||
|
if (buf) {
|
||||||
|
e->GetByteArrayRegion(
|
||||||
|
buffer, offset, length, reinterpret_cast<jbyte*>(buf));
|
||||||
|
r = ::doSend(socket, &address, buf, length);
|
||||||
|
free(buf);
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
jboolean isCopy;
|
||||||
|
uint8_t* buf
|
||||||
|
= static_cast<uint8_t*>(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||||
|
|
||||||
|
r = ::doSend(socket, &address, buf + offset, length);
|
||||||
|
|
||||||
|
e->ReleasePrimitiveArrayCritical(buffer, buf, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r < 0) {
|
||||||
|
if (eagain()) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
throwIOException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" JNIEXPORT void JNICALL
|
extern "C" JNIEXPORT void JNICALL
|
||||||
Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv *e,
|
Java_java_nio_channels_SocketChannel_natThrowWriteError(JNIEnv *e,
|
||||||
jclass,
|
jclass,
|
||||||
@ -693,6 +711,14 @@ Java_java_nio_channels_SocketChannel_natCloseSocket(JNIEnv *,
|
|||||||
doClose(socket);
|
doClose(socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" JNIEXPORT void JNICALL
|
||||||
|
Java_java_nio_channels_DatagramChannel_close(JNIEnv *,
|
||||||
|
jclass,
|
||||||
|
jint socket)
|
||||||
|
{
|
||||||
|
doClose(socket);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class Pipe {
|
class Pipe {
|
||||||
|
@ -10,7 +10,21 @@
|
|||||||
|
|
||||||
package java.io;
|
package java.io;
|
||||||
|
|
||||||
public abstract class Reader implements Closeable {
|
import java.nio.CharBuffer;
|
||||||
|
|
||||||
|
public abstract class Reader implements Closeable, Readable {
|
||||||
|
public int read(CharBuffer buffer) throws IOException {
|
||||||
|
int c = read(buffer.array(),
|
||||||
|
buffer.arrayOffset() + buffer.position(),
|
||||||
|
buffer.remaining());
|
||||||
|
|
||||||
|
if (c > 0) {
|
||||||
|
buffer.position(buffer.position() + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
char[] buffer = new char[1];
|
char[] buffer = new char[1];
|
||||||
int c = read(buffer);
|
int c = read(buffer);
|
||||||
|
18
classpath/java/lang/Readable.java
Normal file
18
classpath/java/lang/Readable.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
/* Copyright (c) 2008-2014, 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;
|
||||||
|
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public interface Readable {
|
||||||
|
int read(CharBuffer buffer) throws IOException;
|
||||||
|
}
|
21
classpath/java/net/BindException.java
Normal file
21
classpath/java/net/BindException.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/* Copyright (c) 2008-2014, 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;
|
||||||
|
|
||||||
|
public class BindException extends SocketException {
|
||||||
|
public BindException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindException() {
|
||||||
|
this(null);
|
||||||
|
}
|
||||||
|
}
|
@ -62,9 +62,17 @@ public class InetAddress {
|
|||||||
(int)((addr[3] + 256) % 256);
|
(int)((addr[3] + 256) % 256);
|
||||||
}
|
}
|
||||||
|
|
||||||
int getRawAddress() {
|
public int getRawAddress() {
|
||||||
return ip;
|
return ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
static native int ipv4AddressForName(String name);
|
static native int ipv4AddressForName(String name) throws UnknownHostException;
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return o instanceof InetAddress && ((InetAddress) o).ip == ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,15 +11,25 @@
|
|||||||
package java.net;
|
package java.net;
|
||||||
|
|
||||||
public class InetSocketAddress extends SocketAddress {
|
public class InetSocketAddress extends SocketAddress {
|
||||||
|
private final String host;
|
||||||
private final InetAddress address;
|
private final InetAddress address;
|
||||||
private final int port;
|
private final int port;
|
||||||
|
|
||||||
public InetSocketAddress(String host, int port) throws UnknownHostException {
|
public InetSocketAddress(String host, int port) {
|
||||||
this.address = InetAddress.getByName(host);
|
InetAddress address;
|
||||||
this.port = port;
|
try {
|
||||||
|
address = InetAddress.getByName(host);
|
||||||
|
host = address.getHostName();
|
||||||
|
} catch (UnknownHostException e) {
|
||||||
|
address = null;
|
||||||
|
}
|
||||||
|
this.host = host;
|
||||||
|
this.address = address;
|
||||||
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InetSocketAddress(InetAddress address, int port) {
|
public InetSocketAddress(InetAddress address, int port) {
|
||||||
|
this.host = address.getHostName();
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
@ -29,10 +39,27 @@ public class InetSocketAddress extends SocketAddress {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String getHostName() {
|
public String getHostName() {
|
||||||
return address.getHostName();
|
return host;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getPort() {
|
public int getPort() {
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o instanceof InetSocketAddress) {
|
||||||
|
InetSocketAddress a = (InetSocketAddress) o;
|
||||||
|
return a.address.equals(address) && a.port == port;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
return port ^ address.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return getHostName() + ":" + port;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,6 +191,9 @@ public class Socket implements Closeable, AutoCloseable {
|
|||||||
outputStream.close();
|
outputStream.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SocketAddress getRemoteSocketAddress() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
|
@ -54,14 +54,14 @@ class ArrayByteBuffer extends ByteBuffer {
|
|||||||
|
|
||||||
public ByteBuffer put(ByteBuffer src) {
|
public ByteBuffer put(ByteBuffer src) {
|
||||||
int length = src.remaining();
|
int length = src.remaining();
|
||||||
checkPut(position, length);
|
checkPut(position, length, false);
|
||||||
src.get(array, arrayOffset + position, length);
|
src.get(array, arrayOffset + position, length);
|
||||||
position += length;
|
position += length;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer put(byte[] src, int offset, int length) {
|
public ByteBuffer put(byte[] src, int offset, int length) {
|
||||||
checkPut(position, length);
|
checkPut(position, length, false);
|
||||||
|
|
||||||
System.arraycopy(src, offset, array, arrayOffset + position, length);
|
System.arraycopy(src, offset, array, arrayOffset + position, length);
|
||||||
position += length;
|
position += length;
|
||||||
@ -70,7 +70,7 @@ class ArrayByteBuffer extends ByteBuffer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer get(byte[] dst, int offset, int length) {
|
public ByteBuffer get(byte[] dst, int offset, int length) {
|
||||||
checkGet(position, length);
|
checkGet(position, length, false);
|
||||||
|
|
||||||
System.arraycopy(array, arrayOffset + position, dst, offset, length);
|
System.arraycopy(array, arrayOffset + position, dst, offset, length);
|
||||||
position += length;
|
position += length;
|
||||||
|
92
classpath/java/nio/ArrayCharBuffer.java
Normal file
92
classpath/java/nio/ArrayCharBuffer.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/* Copyright (c) 2008-2014, 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.nio;
|
||||||
|
|
||||||
|
class ArrayCharBuffer extends CharBuffer {
|
||||||
|
private final char[] array;
|
||||||
|
private final int arrayOffset;
|
||||||
|
|
||||||
|
ArrayCharBuffer(char[] array, int offset, int length, boolean readOnly) {
|
||||||
|
super(readOnly);
|
||||||
|
|
||||||
|
this.array = array;
|
||||||
|
this.arrayOffset = offset;
|
||||||
|
this.capacity = length;
|
||||||
|
this.limit = length;
|
||||||
|
this.position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer asReadOnlyBuffer() {
|
||||||
|
CharBuffer b = new ArrayCharBuffer(array, arrayOffset, capacity, true);
|
||||||
|
b.position(position());
|
||||||
|
b.limit(limit());
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasArray() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[] array() {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer slice() {
|
||||||
|
return new ArrayCharBuffer
|
||||||
|
(array, arrayOffset + position, remaining(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int arrayOffset() {
|
||||||
|
return arrayOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doPut(int position, char val) {
|
||||||
|
array[arrayOffset + position] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer put(CharBuffer src) {
|
||||||
|
int length = src.remaining();
|
||||||
|
checkPut(position, length, false);
|
||||||
|
src.get(array, arrayOffset + position, length);
|
||||||
|
position += length;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer put(char[] src, int offset, int length) {
|
||||||
|
checkPut(position, length, false);
|
||||||
|
|
||||||
|
System.arraycopy(src, offset, array, arrayOffset + position, length);
|
||||||
|
position += length;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer get(char[] dst, int offset, int length) {
|
||||||
|
checkGet(position, length, false);
|
||||||
|
|
||||||
|
System.arraycopy(array, arrayOffset + position, dst, offset, length);
|
||||||
|
position += length;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected char doGet(int position) {
|
||||||
|
return array[arrayOffset+position];
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "(ArrayCharBuffer with array: " + array
|
||||||
|
+ " arrayOffset: " + arrayOffset
|
||||||
|
+ " position: " + position
|
||||||
|
+ " limit: " + limit
|
||||||
|
+ " capacity: " + capacity + ")";
|
||||||
|
}
|
||||||
|
}
|
14
classpath/java/nio/BufferOverflowException.java
Normal file
14
classpath/java/nio/BufferOverflowException.java
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
/* Copyright (c) 2008-2014, 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.nio;
|
||||||
|
|
||||||
|
public class BufferOverflowException extends RuntimeException {
|
||||||
|
}
|
@ -69,7 +69,7 @@ public abstract class ByteBuffer
|
|||||||
|
|
||||||
public ByteBuffer put(ByteBuffer src) {
|
public ByteBuffer put(ByteBuffer src) {
|
||||||
if (src.hasArray()) {
|
if (src.hasArray()) {
|
||||||
checkPut(position, src.remaining());
|
checkPut(position, src.remaining(), false);
|
||||||
|
|
||||||
put(src.array(), src.arrayOffset() + src.position, src.remaining());
|
put(src.array(), src.arrayOffset() + src.position, src.remaining());
|
||||||
src.position(src.position() + src.remaining());
|
src.position(src.position() + src.remaining());
|
||||||
@ -107,13 +107,14 @@ public abstract class ByteBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer put(int offset, byte val) {
|
public ByteBuffer put(int offset, byte val) {
|
||||||
checkPut(offset, 1);
|
checkPut(offset, 1, true);
|
||||||
doPut(offset, val);
|
doPut(offset, val);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer put(byte val) {
|
public ByteBuffer put(byte val) {
|
||||||
put(position, val);
|
checkPut(position, 1, false);
|
||||||
|
doPut(position, val);
|
||||||
++ position;
|
++ position;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -122,9 +123,7 @@ public abstract class ByteBuffer
|
|||||||
return put(arr, 0, arr.length);
|
return put(arr, 0, arr.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer putLong(int position, long val) {
|
private void rawPutLong(int position, long val) {
|
||||||
checkPut(position, 8);
|
|
||||||
|
|
||||||
doPut(position , (byte) ((val >> 56) & 0xff));
|
doPut(position , (byte) ((val >> 56) & 0xff));
|
||||||
doPut(position + 1, (byte) ((val >> 48) & 0xff));
|
doPut(position + 1, (byte) ((val >> 48) & 0xff));
|
||||||
doPut(position + 2, (byte) ((val >> 40) & 0xff));
|
doPut(position + 2, (byte) ((val >> 40) & 0xff));
|
||||||
@ -133,54 +132,75 @@ public abstract class ByteBuffer
|
|||||||
doPut(position + 5, (byte) ((val >> 16) & 0xff));
|
doPut(position + 5, (byte) ((val >> 16) & 0xff));
|
||||||
doPut(position + 6, (byte) ((val >> 8) & 0xff));
|
doPut(position + 6, (byte) ((val >> 8) & 0xff));
|
||||||
doPut(position + 7, (byte) ((val ) & 0xff));
|
doPut(position + 7, (byte) ((val ) & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rawPutInt(int position, int val) {
|
||||||
|
doPut(position , (byte) ((val >> 24) & 0xff));
|
||||||
|
doPut(position + 1, (byte) ((val >> 16) & 0xff));
|
||||||
|
doPut(position + 2, (byte) ((val >> 8) & 0xff));
|
||||||
|
doPut(position + 3, (byte) ((val ) & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void rawPutShort(int position, short val) {
|
||||||
|
doPut(position , (byte) ((val >> 8) & 0xff));
|
||||||
|
doPut(position + 1, (byte) ((val ) & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ByteBuffer putLong(int position, long val) {
|
||||||
|
checkPut(position, 8, true);
|
||||||
|
|
||||||
|
rawPutLong(position, val);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer putInt(int position, int val) {
|
public ByteBuffer putInt(int position, int val) {
|
||||||
checkPut(position, 4);
|
checkPut(position, 4, true);
|
||||||
|
|
||||||
doPut(position , (byte) ((val >> 24) & 0xff));
|
rawPutInt(position, val);
|
||||||
doPut(position + 1, (byte) ((val >> 16) & 0xff));
|
|
||||||
doPut(position + 2, (byte) ((val >> 8) & 0xff));
|
|
||||||
doPut(position + 3, (byte) ((val ) & 0xff));
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer putShort(int position, short val) {
|
public ByteBuffer putShort(int position, short val) {
|
||||||
checkPut(position, 2);
|
checkPut(position, 2, true);
|
||||||
|
|
||||||
doPut(position , (byte) ((val >> 8) & 0xff));
|
rawPutShort(position, val);
|
||||||
doPut(position + 1, (byte) ((val ) & 0xff));
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer putLong(long val) {
|
public ByteBuffer putLong(long val) {
|
||||||
putLong(position, val);
|
checkPut(position, 8, false);
|
||||||
|
|
||||||
|
rawPutLong(position, val);
|
||||||
position += 8;
|
position += 8;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer putInt(int val) {
|
public ByteBuffer putInt(int val) {
|
||||||
putInt(position, val);
|
checkPut(position, 4, false);
|
||||||
|
|
||||||
|
rawPutInt(position, val);
|
||||||
position += 4;
|
position += 4;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer putShort(short val) {
|
public ByteBuffer putShort(short val) {
|
||||||
putShort(position, val);
|
checkPut(position, 2, false);
|
||||||
|
|
||||||
|
rawPutShort(position, val);
|
||||||
position += 2;
|
position += 2;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte get() {
|
public byte get() {
|
||||||
return get(position++);
|
checkGet(position, 1, false);
|
||||||
|
return doGet(position++);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte get(int position) {
|
public byte get(int position) {
|
||||||
checkGet(position, 1);
|
checkGet(position, 1, true);
|
||||||
return doGet(position);
|
return doGet(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,8 +209,24 @@ public abstract class ByteBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long getLong(int position) {
|
public long getLong(int position) {
|
||||||
checkGet(position, 8);
|
checkGet(position, 8, true);
|
||||||
|
|
||||||
|
return rawGetLong(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getInt(int position) {
|
||||||
|
checkGet(position, 4, true);
|
||||||
|
|
||||||
|
return rawGetInt(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getShort(int position) {
|
||||||
|
checkGet(position, 2, true);
|
||||||
|
|
||||||
|
return rawGetShort(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long rawGetLong(int position) {
|
||||||
return (((long) (doGet(position ) & 0xFF)) << 56)
|
return (((long) (doGet(position ) & 0xFF)) << 56)
|
||||||
| (((long) (doGet(position + 1) & 0xFF)) << 48)
|
| (((long) (doGet(position + 1) & 0xFF)) << 48)
|
||||||
| (((long) (doGet(position + 2) & 0xFF)) << 40)
|
| (((long) (doGet(position + 2) & 0xFF)) << 40)
|
||||||
@ -201,48 +237,60 @@ public abstract class ByteBuffer
|
|||||||
| (((long) (doGet(position + 7) & 0xFF)) );
|
| (((long) (doGet(position + 7) & 0xFF)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getInt(int position) {
|
private int rawGetInt(int position) {
|
||||||
checkGet(position, 4);
|
|
||||||
|
|
||||||
return (((int) (doGet(position ) & 0xFF)) << 24)
|
return (((int) (doGet(position ) & 0xFF)) << 24)
|
||||||
| (((int) (doGet(position + 1) & 0xFF)) << 16)
|
| (((int) (doGet(position + 1) & 0xFF)) << 16)
|
||||||
| (((int) (doGet(position + 2) & 0xFF)) << 8)
|
| (((int) (doGet(position + 2) & 0xFF)) << 8)
|
||||||
| (((int) (doGet(position + 3) & 0xFF)) );
|
| (((int) (doGet(position + 3) & 0xFF)) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getShort(int position) {
|
private short rawGetShort(int position) {
|
||||||
checkGet(position, 2);
|
|
||||||
|
|
||||||
return (short) (( ((int) (doGet(position ) & 0xFF)) << 8)
|
return (short) (( ((int) (doGet(position ) & 0xFF)) << 8)
|
||||||
| (((int) (doGet(position + 1) & 0xFF)) ));
|
| (((int) (doGet(position + 1) & 0xFF)) ));
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getLong() {
|
public long getLong() {
|
||||||
long r = getLong(position);
|
checkGet(position, 8, false);
|
||||||
|
|
||||||
|
long r = rawGetLong(position);
|
||||||
position += 8;
|
position += 8;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getInt() {
|
public int getInt() {
|
||||||
int r = getInt(position);
|
checkGet(position, 4, false);
|
||||||
|
|
||||||
|
int r = rawGetInt(position);
|
||||||
position += 4;
|
position += 4;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
public short getShort() {
|
public short getShort() {
|
||||||
short r = getShort(position);
|
checkGet(position, 2, false);
|
||||||
|
|
||||||
|
short r = rawGetShort(position);
|
||||||
position += 2;
|
position += 2;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void checkPut(int position, int amount) {
|
protected void checkPut(int position, int amount, boolean absolute) {
|
||||||
if (readOnly) throw new ReadOnlyBufferException();
|
if (readOnly) {
|
||||||
if (position < 0 || position+amount > limit)
|
throw new ReadOnlyBufferException();
|
||||||
throw new IndexOutOfBoundsException();
|
}
|
||||||
|
|
||||||
|
if (position < 0 || position+amount > limit) {
|
||||||
|
throw absolute
|
||||||
|
? new IndexOutOfBoundsException()
|
||||||
|
: new BufferOverflowException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void checkGet(int position, int amount) {
|
protected void checkGet(int position, int amount, boolean absolute) {
|
||||||
if (amount > limit-position) throw new IndexOutOfBoundsException();
|
if (amount > limit-position) {
|
||||||
|
throw absolute
|
||||||
|
? new IndexOutOfBoundsException()
|
||||||
|
: new BufferUnderflowException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer order(ByteOrder order) {
|
public ByteBuffer order(ByteOrder order) {
|
||||||
|
154
classpath/java/nio/CharBuffer.java
Normal file
154
classpath/java/nio/CharBuffer.java
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/* Copyright (c) 2008-2014, 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.nio;
|
||||||
|
|
||||||
|
public abstract class CharBuffer
|
||||||
|
extends Buffer
|
||||||
|
implements Comparable<CharBuffer>
|
||||||
|
{
|
||||||
|
private final boolean readOnly;
|
||||||
|
|
||||||
|
protected CharBuffer(boolean readOnly) {
|
||||||
|
this.readOnly = readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CharBuffer allocate(int capacity) {
|
||||||
|
return new ArrayCharBuffer(new char[capacity], 0, capacity, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CharBuffer wrap(char[] array) {
|
||||||
|
return wrap(array, 0, array.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static CharBuffer wrap(char[] array, int offset, int length) {
|
||||||
|
return new ArrayCharBuffer(array, offset, length, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract CharBuffer asReadOnlyBuffer();
|
||||||
|
|
||||||
|
public abstract CharBuffer slice();
|
||||||
|
|
||||||
|
protected abstract void doPut(int offset, char value);
|
||||||
|
|
||||||
|
public abstract CharBuffer put(char[] src, int offset, int length);
|
||||||
|
|
||||||
|
protected abstract char doGet(int offset);
|
||||||
|
|
||||||
|
public abstract CharBuffer get(char[] dst, int offset, int length);
|
||||||
|
|
||||||
|
public boolean hasArray() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer compact() {
|
||||||
|
int remaining = remaining();
|
||||||
|
|
||||||
|
if (position != 0) {
|
||||||
|
CharBuffer b = slice();
|
||||||
|
position = 0;
|
||||||
|
put(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
position = remaining;
|
||||||
|
limit(capacity());
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer put(CharBuffer src) {
|
||||||
|
if (src.hasArray()) {
|
||||||
|
checkPut(position, src.remaining(), false);
|
||||||
|
|
||||||
|
put(src.array(), src.arrayOffset() + src.position, src.remaining());
|
||||||
|
src.position(src.position() + src.remaining());
|
||||||
|
|
||||||
|
return this;
|
||||||
|
} else {
|
||||||
|
char[] buffer = new char[src.remaining()];
|
||||||
|
src.get(buffer);
|
||||||
|
return put(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int compareTo(CharBuffer o) {
|
||||||
|
int end = (remaining() < o.remaining() ? remaining() : o.remaining());
|
||||||
|
|
||||||
|
for (int i = 0; i < end; ++i) {
|
||||||
|
int d = get(position + i) - o.get(o.position + i);
|
||||||
|
if (d != 0) {
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return remaining() - o.remaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return o instanceof CharBuffer && compareTo((CharBuffer) o) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public char[] array() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int arrayOffset() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer put(int offset, char val) {
|
||||||
|
checkPut(offset, 1, true);
|
||||||
|
doPut(offset, val);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer put(char val) {
|
||||||
|
put(position, val);
|
||||||
|
++ position;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer put(char[] arr) {
|
||||||
|
return put(arr, 0, arr.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public char get() {
|
||||||
|
checkGet(position, 1, false);
|
||||||
|
return doGet(position++);
|
||||||
|
}
|
||||||
|
|
||||||
|
public char get(int position) {
|
||||||
|
checkGet(position, 1, true);
|
||||||
|
return doGet(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CharBuffer get(char[] dst) {
|
||||||
|
return get(dst, 0, dst.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkPut(int position, int amount, boolean absolute) {
|
||||||
|
if (readOnly) {
|
||||||
|
throw new ReadOnlyBufferException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (position < 0 || position+amount > limit) {
|
||||||
|
throw absolute
|
||||||
|
? new IndexOutOfBoundsException()
|
||||||
|
: new BufferOverflowException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkGet(int position, int amount, boolean absolute) {
|
||||||
|
if (amount > limit-position) {
|
||||||
|
throw absolute
|
||||||
|
? new IndexOutOfBoundsException()
|
||||||
|
: new BufferUnderflowException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -48,7 +48,7 @@ class DirectByteBuffer extends ByteBuffer {
|
|||||||
|
|
||||||
public ByteBuffer put(ByteBuffer src) {
|
public ByteBuffer put(ByteBuffer src) {
|
||||||
if (src instanceof DirectByteBuffer) {
|
if (src instanceof DirectByteBuffer) {
|
||||||
checkPut(position, src.remaining());
|
checkPut(position, src.remaining(), false);
|
||||||
|
|
||||||
DirectByteBuffer b = (DirectByteBuffer) src;
|
DirectByteBuffer b = (DirectByteBuffer) src;
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ class DirectByteBuffer extends ByteBuffer {
|
|||||||
throw new ArrayIndexOutOfBoundsException();
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkPut(position, length);
|
checkPut(position, length, false);
|
||||||
|
|
||||||
unsafe.copyMemory
|
unsafe.copyMemory
|
||||||
(src, baseOffset + offset, null, address + position, length);
|
(src, baseOffset + offset, null, address + position, length);
|
||||||
@ -84,7 +84,7 @@ class DirectByteBuffer extends ByteBuffer {
|
|||||||
throw new ArrayIndexOutOfBoundsException();
|
throw new ArrayIndexOutOfBoundsException();
|
||||||
}
|
}
|
||||||
|
|
||||||
checkGet(position, length);
|
checkGet(position, length, false);
|
||||||
|
|
||||||
unsafe.copyMemory
|
unsafe.copyMemory
|
||||||
(null, address + position, dst, baseOffset + offset, length);
|
(null, address + position, dst, baseOffset + offset, length);
|
||||||
|
@ -26,7 +26,7 @@ public class DatagramChannel extends SelectableChannel
|
|||||||
{
|
{
|
||||||
public static final int InvalidSocket = -1;
|
public static final int InvalidSocket = -1;
|
||||||
|
|
||||||
private int socket = InvalidSocket;
|
private int socket = makeSocket();
|
||||||
private boolean blocking = true;
|
private boolean blocking = true;
|
||||||
private boolean connected = false;
|
private boolean connected = false;
|
||||||
|
|
||||||
@ -80,8 +80,12 @@ public class DatagramChannel extends SelectableChannel
|
|||||||
throw new UnsupportedAddressTypeException();
|
throw new UnsupportedAddressTypeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
socket = bind(inetAddress.getHostName(), inetAddress.getPort());
|
if (inetAddress == null) {
|
||||||
configureBlocking();
|
bind(socket, 0, 0);
|
||||||
|
} else {
|
||||||
|
bind(socket, inetAddress.getAddress().getRawAddress(),
|
||||||
|
inetAddress.getPort());
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -94,10 +98,8 @@ public class DatagramChannel extends SelectableChannel
|
|||||||
throw new UnsupportedAddressTypeException();
|
throw new UnsupportedAddressTypeException();
|
||||||
}
|
}
|
||||||
|
|
||||||
socket = connect(inetAddress.getHostName(), inetAddress.getPort());
|
connected = connect(socket, inetAddress.getAddress().getRawAddress(),
|
||||||
configureBlocking();
|
inetAddress.getPort());
|
||||||
|
|
||||||
if (socket != 0) connected = true;
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -145,6 +147,31 @@ public class DatagramChannel extends SelectableChannel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int send(ByteBuffer b, SocketAddress address) throws IOException {
|
||||||
|
if (b.remaining() == 0) return 0;
|
||||||
|
|
||||||
|
InetSocketAddress inetAddress;
|
||||||
|
try {
|
||||||
|
inetAddress = (InetSocketAddress) address;
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new UnsupportedAddressTypeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] array = b.array();
|
||||||
|
if (array == null) throw new NullPointerException();
|
||||||
|
|
||||||
|
int c = send
|
||||||
|
(socket, inetAddress.getAddress().getRawAddress(),
|
||||||
|
inetAddress.getPort(), array, b.arrayOffset() + b.position(),
|
||||||
|
b.remaining(), blocking);
|
||||||
|
|
||||||
|
if (c > 0) {
|
||||||
|
b.position(b.position() + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
private static String ipv4ToString(int address) {
|
private static String ipv4ToString(int address) {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
@ -178,22 +205,35 @@ public class DatagramChannel extends SelectableChannel
|
|||||||
|
|
||||||
/** TODO: This is probably incomplete. */
|
/** TODO: This is probably incomplete. */
|
||||||
public DatagramChannel disconnect() throws IOException {
|
public DatagramChannel disconnect() throws IOException {
|
||||||
close();
|
connect(socket, 0, 0);
|
||||||
connected = false;
|
connected = false;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (isOpen()) {
|
||||||
|
super.close();
|
||||||
|
close(socket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native int makeSocket();
|
||||||
private static native void configureBlocking(int socket, boolean blocking)
|
private static native void configureBlocking(int socket, boolean blocking)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
private static native int bind(String hostname, int port)
|
private static native void bind(int socket, int host, int port)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
private static native int connect(String hostname, int port)
|
private static native boolean connect(int socket, int host, int port)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
private static native int write(int socket, byte[] array, int offset,
|
private static native int write(int socket, byte[] array, int offset,
|
||||||
int length, boolean blocking)
|
int length, boolean blocking)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
private static native int send(int socket, int host, int port,
|
||||||
|
byte[] array, int offset,
|
||||||
|
int length, boolean blocking)
|
||||||
|
throws IOException;
|
||||||
private static native int receive(int socket, byte[] array, int offset,
|
private static native int receive(int socket, byte[] array, int offset,
|
||||||
int length, boolean blocking,
|
int length, boolean blocking,
|
||||||
int[] address)
|
int[] address)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
private static native void close(int socket);
|
||||||
}
|
}
|
||||||
|
@ -66,10 +66,10 @@ public class ServerSocketChannel extends SelectableChannel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int doListen(String host, int port) throws IOException {
|
private void doListen(int socket, int host, int port) throws IOException {
|
||||||
Socket.init();
|
Socket.init();
|
||||||
|
|
||||||
return natDoListen(host, port);
|
natDoListen(socket, host, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Handle extends ServerSocket {
|
public class Handle extends ServerSocket {
|
||||||
@ -82,11 +82,10 @@ public class ServerSocketChannel extends SelectableChannel {
|
|||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
channel.socket = doListen(a.getHostName(), a.getPort());
|
doListen(channel.socket, a.getAddress().getRawAddress(), a.getPort());
|
||||||
channel.configureBlocking(channel.isBlocking());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native int natDoAccept(int socket) throws IOException;
|
private static native int natDoAccept(int socket) throws IOException;
|
||||||
private static native int natDoListen(String host, int port) throws IOException;
|
private static native void natDoListen(int socket, int host, int port) throws IOException;
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ public class SocketChannel extends SelectableChannel
|
|||||||
{
|
{
|
||||||
public static final int InvalidSocket = -1;
|
public static final int InvalidSocket = -1;
|
||||||
|
|
||||||
int socket = InvalidSocket;
|
int socket = makeSocket();
|
||||||
boolean connected = false;
|
boolean connected = false;
|
||||||
boolean readyToConnect = false;
|
boolean readyToConnect = false;
|
||||||
boolean blocking = true;
|
boolean blocking = true;
|
||||||
@ -64,7 +64,7 @@ public class SocketChannel extends SelectableChannel
|
|||||||
} catch (ClassCastException e) {
|
} catch (ClassCastException e) {
|
||||||
throw new UnsupportedAddressTypeException();
|
throw new UnsupportedAddressTypeException();
|
||||||
}
|
}
|
||||||
socket = doConnect(a.getHostName(), a.getPort());
|
doConnect(socket, a.getAddress().getRawAddress(), a.getPort());
|
||||||
configureBlocking(blocking);
|
configureBlocking(blocking);
|
||||||
return connected;
|
return connected;
|
||||||
}
|
}
|
||||||
@ -98,13 +98,10 @@ public class SocketChannel extends SelectableChannel
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int doConnect(String host, int port) throws IOException {
|
private void doConnect(int socket, int host, int port)
|
||||||
if (host == null) throw new NullPointerException();
|
throws IOException
|
||||||
|
{
|
||||||
boolean b[] = new boolean[1];
|
connected = natDoConnect(socket, host, port);
|
||||||
int s = natDoConnect(host, port, blocking, b);
|
|
||||||
connected = b[0];
|
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int read(ByteBuffer b) throws IOException {
|
public int read(ByteBuffer b) throws IOException {
|
||||||
@ -170,21 +167,40 @@ public class SocketChannel extends SelectableChannel
|
|||||||
|
|
||||||
public class Handle extends Socket {
|
public class Handle extends Socket {
|
||||||
public Handle() throws IOException {
|
public Handle() throws IOException {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTcpNoDelay(boolean on) throws SocketException {
|
public void setTcpNoDelay(boolean on) throws SocketException {
|
||||||
natSetTcpNoDelay(socket, on);
|
natSetTcpNoDelay(socket, on);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void bind(SocketAddress address)
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
InetSocketAddress a;
|
||||||
|
try {
|
||||||
|
a = (InetSocketAddress) address;
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == null) {
|
||||||
|
bind(socket, 0, 0);
|
||||||
|
} else {
|
||||||
|
bind(socket, a.getAddress().getRawAddress(), a.getPort());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static native int makeSocket();
|
||||||
private static native void configureBlocking(int socket, boolean blocking)
|
private static native void configureBlocking(int socket, boolean blocking)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
|
||||||
private static native void natSetTcpNoDelay(int socket, boolean on)
|
private static native void natSetTcpNoDelay(int socket, boolean on)
|
||||||
throws SocketException;
|
throws SocketException;
|
||||||
|
private static native void bind(int socket, int host, int port)
|
||||||
private static native int natDoConnect(String host, int port, boolean blocking, boolean[] connected)
|
throws IOException;
|
||||||
|
private static native boolean natDoConnect(int socket, int host, int port)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
private static native void natFinishConnect(int socket)
|
private static native void natFinishConnect(int socket)
|
||||||
throws IOException;
|
throws IOException;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.BufferUnderflowException;
|
||||||
|
import java.nio.BufferOverflowException;
|
||||||
|
|
||||||
public class Buffers {
|
public class Buffers {
|
||||||
static {
|
static {
|
||||||
@ -57,7 +59,7 @@ public class Buffers {
|
|||||||
|
|
||||||
private static native void freeNative(ByteBuffer b);
|
private static native void freeNative(ByteBuffer b);
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) throws Exception {
|
||||||
Factory array = new Factory() {
|
Factory array = new Factory() {
|
||||||
public ByteBuffer allocate(int capacity) {
|
public ByteBuffer allocate(int capacity) {
|
||||||
return ByteBuffer.allocate(capacity);
|
return ByteBuffer.allocate(capacity);
|
||||||
@ -99,6 +101,34 @@ public class Buffers {
|
|||||||
test(native_, array);
|
test(native_, array);
|
||||||
test(native_, direct);
|
test(native_, direct);
|
||||||
test(native_, native_);
|
test(native_, native_);
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteBuffer.allocate(1).getInt();
|
||||||
|
expect(false);
|
||||||
|
} catch (BufferUnderflowException e) {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteBuffer.allocate(1).getInt(0);
|
||||||
|
expect(false);
|
||||||
|
} catch (IndexOutOfBoundsException e) {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteBuffer.allocate(1).putInt(1);
|
||||||
|
expect(false);
|
||||||
|
} catch (BufferOverflowException e) {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteBuffer.allocate(1).putInt(0, 1);
|
||||||
|
expect(false);
|
||||||
|
} catch (IndexOutOfBoundsException e) {
|
||||||
|
// cool
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private interface Factory {
|
private interface Factory {
|
||||||
|
@ -22,20 +22,28 @@ public class Datagrams {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
test(true);
|
||||||
|
test(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void test(boolean send) throws Exception {
|
||||||
final String Hostname = "localhost";
|
final String Hostname = "localhost";
|
||||||
final int Port = 22043;
|
final int InPort = 22043;
|
||||||
final SocketAddress Address = new InetSocketAddress(Hostname, Port);
|
final int OutPort = 22044;
|
||||||
|
final SocketAddress InAddress = new InetSocketAddress(Hostname, InPort);
|
||||||
|
final SocketAddress OutAddress = new InetSocketAddress(Hostname, OutPort);
|
||||||
final byte[] Message = "hello, world!".getBytes();
|
final byte[] Message = "hello, world!".getBytes();
|
||||||
|
|
||||||
DatagramChannel out = DatagramChannel.open();
|
DatagramChannel out = DatagramChannel.open();
|
||||||
try {
|
try {
|
||||||
out.configureBlocking(false);
|
out.configureBlocking(false);
|
||||||
out.connect(Address);
|
out.socket().bind(OutAddress);
|
||||||
|
if (! send) out.connect(InAddress);
|
||||||
|
|
||||||
DatagramChannel in = DatagramChannel.open();
|
DatagramChannel in = DatagramChannel.open();
|
||||||
try {
|
try {
|
||||||
in.configureBlocking(false);
|
in.configureBlocking(false);
|
||||||
in.socket().bind(Address);
|
in.socket().bind(InAddress);
|
||||||
|
|
||||||
Selector selector = Selector.open();
|
Selector selector = Selector.open();
|
||||||
try {
|
try {
|
||||||
@ -53,14 +61,18 @@ public class Datagrams {
|
|||||||
switch (state) {
|
switch (state) {
|
||||||
case 0: {
|
case 0: {
|
||||||
if (outKey.isWritable()) {
|
if (outKey.isWritable()) {
|
||||||
out.write(ByteBuffer.wrap(Message));
|
if (send) {
|
||||||
|
out.send(ByteBuffer.wrap(Message), InAddress);
|
||||||
|
} else {
|
||||||
|
out.write(ByteBuffer.wrap(Message));
|
||||||
|
}
|
||||||
state = 1;
|
state = 1;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case 1: {
|
case 1: {
|
||||||
if (inKey.isReadable()) {
|
if (inKey.isReadable()) {
|
||||||
in.receive(inBuffer);
|
expect(in.receive(inBuffer).equals(OutAddress));
|
||||||
if (! inBuffer.hasRemaining()) {
|
if (! inBuffer.hasRemaining()) {
|
||||||
expect(equal(inBuffer.array(),
|
expect(equal(inBuffer.array(),
|
||||||
inBuffer.arrayOffset(),
|
inBuffer.arrayOffset(),
|
||||||
|
@ -206,5 +206,12 @@ public class Strings {
|
|||||||
expect("abc".lastIndexOf('b', 100) == 1);
|
expect("abc".lastIndexOf('b', 100) == 1);
|
||||||
|
|
||||||
testTrivialPattern();
|
testTrivialPattern();
|
||||||
|
|
||||||
|
{ String s = "hello, world!";
|
||||||
|
java.nio.CharBuffer buffer = java.nio.CharBuffer.allocate(s.length());
|
||||||
|
new java.io.InputStreamReader
|
||||||
|
(new java.io.ByteArrayInputStream(s.getBytes())).read(buffer);
|
||||||
|
expect(s.equals(new String(buffer.array())));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user