mirror of
https://github.com/corda/corda.git
synced 2025-01-19 11:16:54 +00:00
implement DatagramChannel.receive and fix Datagrams to be Java 6 compatible
This commit is contained in:
parent
d8483d720d
commit
9974d91648
@ -337,6 +337,26 @@ doRead(int fd, void* buffer, size_t count)
|
||||
#endif
|
||||
}
|
||||
|
||||
int
|
||||
doRecv(int fd, void* buffer, size_t count, int32_t* host, int32_t* port)
|
||||
{
|
||||
sockaddr address;
|
||||
socklen_t length = sizeof(address);
|
||||
int r = recvfrom
|
||||
(fd, static_cast<char*>(buffer), count, 0, &address, &length);
|
||||
|
||||
if (r > 0) {
|
||||
sockaddr_in a; memcpy(&a, &address, length);
|
||||
*host = ntohl(a.sin_addr.s_addr);
|
||||
*port = ntohs(a.sin_port);
|
||||
} else {
|
||||
*host = 0;
|
||||
*port = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int
|
||||
doWrite(int fd, const void* buffer, size_t count)
|
||||
{
|
||||
@ -529,16 +549,54 @@ Java_java_nio_channels_SocketChannel_natRead(JNIEnv *e,
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_java_nio_channels_DatagramChannel_read(JNIEnv* e,
|
||||
jclass c,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking)
|
||||
Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
|
||||
jclass,
|
||||
jint socket,
|
||||
jbyteArray buffer,
|
||||
jint offset,
|
||||
jint length,
|
||||
jboolean blocking,
|
||||
jintArray address)
|
||||
{
|
||||
return Java_java_nio_channels_SocketChannel_natRead
|
||||
(e, c, socket, buffer, offset, length, blocking);
|
||||
int r;
|
||||
int32_t host;
|
||||
int32_t port;
|
||||
if (blocking) {
|
||||
uint8_t* buf = static_cast<uint8_t*>(allocate(e, length));
|
||||
if (buf) {
|
||||
r = ::doRecv(socket, buf, length, &host, &port);
|
||||
if (r > 0) {
|
||||
e->SetByteArrayRegion
|
||||
(buffer, offset, r, reinterpret_cast<jbyte*>(buf));
|
||||
}
|
||||
free(buf);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
jboolean isCopy;
|
||||
uint8_t* buf = static_cast<uint8_t*>
|
||||
(e->GetPrimitiveArrayCritical(buffer, &isCopy));
|
||||
|
||||
r = ::doRecv(socket, buf + offset, length, &host, &port);
|
||||
|
||||
e->ReleasePrimitiveArrayCritical(buffer, buf, 0);
|
||||
}
|
||||
|
||||
if (r < 0) {
|
||||
if (eagain()) {
|
||||
return 0;
|
||||
} else {
|
||||
throwIOException(e);
|
||||
}
|
||||
} else if (r == 0) {
|
||||
return -1;
|
||||
} else {
|
||||
e->SetIntArrayRegion(address, 0, 1, &host);
|
||||
e->SetIntArrayRegion(address, 1, 1, &port);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
|
19
classpath/java/net/DatagramSocket.java
Normal file
19
classpath/java/net/DatagramSocket.java
Normal file
@ -0,0 +1,19 @@
|
||||
/* Copyright (c) 2012, 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.IOException;
|
||||
|
||||
public abstract class DatagramSocket {
|
||||
public abstract SocketAddress getRemoteSocketAddress();
|
||||
|
||||
public abstract void bind(SocketAddress address) throws SocketException;
|
||||
}
|
@ -16,6 +16,8 @@ import java.net.SocketAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolFamily;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.StandardProtocolFamily;
|
||||
|
||||
public class DatagramChannel extends SelectableChannel
|
||||
@ -26,7 +28,7 @@ public class DatagramChannel extends SelectableChannel
|
||||
private int socket = InvalidSocket;
|
||||
private boolean blocking = true;
|
||||
|
||||
public DatagramChannel configureBlocking(boolean v) throws IOException {
|
||||
public SelectableChannel configureBlocking(boolean v) throws IOException {
|
||||
blocking = v;
|
||||
if (socket != InvalidSocket) {
|
||||
configureBlocking(socket, v);
|
||||
@ -54,6 +56,16 @@ public class DatagramChannel extends SelectableChannel
|
||||
}
|
||||
}
|
||||
|
||||
public static DatagramChannel open()
|
||||
throws IOException
|
||||
{
|
||||
return open(StandardProtocolFamily.INET);
|
||||
}
|
||||
|
||||
public DatagramSocket socket() {
|
||||
return new Handle();
|
||||
}
|
||||
|
||||
public DatagramChannel bind(SocketAddress address) throws IOException {
|
||||
InetSocketAddress inetAddress;
|
||||
try {
|
||||
@ -97,19 +109,59 @@ public class DatagramChannel extends SelectableChannel
|
||||
}
|
||||
|
||||
public int read(ByteBuffer b) throws IOException {
|
||||
if (b.remaining() == 0) return 0;
|
||||
int p = b.position();
|
||||
receive(b);
|
||||
return b.position() - p;
|
||||
}
|
||||
|
||||
public SocketAddress receive(ByteBuffer b) throws IOException {
|
||||
if (b.remaining() == 0) return null;
|
||||
|
||||
byte[] array = b.array();
|
||||
if (array == null) throw new NullPointerException();
|
||||
|
||||
int c = read
|
||||
(socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking);
|
||||
int[] address = new int[2];
|
||||
|
||||
int c = receive
|
||||
(socket, array, b.arrayOffset() + b.position(), b.remaining(), blocking,
|
||||
address);
|
||||
|
||||
if (c > 0) {
|
||||
b.position(b.position() + c);
|
||||
|
||||
return new InetSocketAddress(ipv4ToString(address[0]), address[1]);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static String ipv4ToString(int address) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( address >> 24 ).append('.')
|
||||
.append((address >> 16) & 0xFF).append('.')
|
||||
.append((address >> 8) & 0xFF).append('.')
|
||||
.append( address & 0xFF);
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public class Handle extends DatagramSocket {
|
||||
public SocketAddress getRemoteSocketAddress() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
return c;
|
||||
public void bind(SocketAddress address) throws SocketException {
|
||||
try {
|
||||
DatagramChannel.this.bind(address);
|
||||
} catch (SocketException e) {
|
||||
throw e;
|
||||
} catch (IOException e) {
|
||||
SocketException se = new SocketException();
|
||||
se.initCause(e);
|
||||
throw se;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static native void configureBlocking(int socket, boolean blocking)
|
||||
@ -121,7 +173,8 @@ public class DatagramChannel extends SelectableChannel
|
||||
private static native int write(int socket, byte[] array, int offset,
|
||||
int length, boolean blocking)
|
||||
throws IOException;
|
||||
private static native int read(int socket, byte[] array, int offset,
|
||||
int length, boolean blocking)
|
||||
private static native int receive(int socket, byte[] array, int offset,
|
||||
int length, boolean blocking,
|
||||
int[] address)
|
||||
throws IOException;
|
||||
}
|
||||
|
@ -27,15 +27,15 @@ public class Datagrams {
|
||||
final SocketAddress Address = new InetSocketAddress(Hostname, Port);
|
||||
final byte[] Message = "hello, world!".getBytes();
|
||||
|
||||
DatagramChannel out = DatagramChannel.open(StandardProtocolFamily.INET);
|
||||
DatagramChannel out = DatagramChannel.open();
|
||||
try {
|
||||
out.configureBlocking(false);
|
||||
out.connect(Address);
|
||||
|
||||
DatagramChannel in = DatagramChannel.open(StandardProtocolFamily.INET);
|
||||
DatagramChannel in = DatagramChannel.open();
|
||||
try {
|
||||
in.configureBlocking(false);
|
||||
in.bind(Address);
|
||||
in.socket().bind(Address);
|
||||
|
||||
Selector selector = Selector.open();
|
||||
try {
|
||||
@ -60,7 +60,7 @@ public class Datagrams {
|
||||
|
||||
case 1: {
|
||||
if (inKey.isReadable()) {
|
||||
in.read(inBuffer);
|
||||
in.receive(inBuffer);
|
||||
if (! inBuffer.hasRemaining()) {
|
||||
expect(equal(inBuffer.array(),
|
||||
inBuffer.arrayOffset(),
|
||||
|
Loading…
Reference in New Issue
Block a user