Permalink
Browse files

implement DatagramChannel.receive and fix Datagrams to be Java 6 comp…

…atible
  • Loading branch information...
1 parent d8483d7 commit 9974d9164835aaa4590d6d085f07f538e7fe84cd @dicej dicej committed Jul 10, 2012
View
@@ -338,6 +338,26 @@ doRead(int fd, void* buffer, size_t count)
}
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)
{
#ifdef PLATFORM_WINDOWS
@@ -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)
-{
- return Java_java_nio_channels_SocketChannel_natRead
- (e, c, socket, buffer, offset, length, blocking);
+Java_java_nio_channels_DatagramChannel_receive(JNIEnv* e,
+ jclass,
+ jint socket,
+ jbyteArray buffer,
+ jint offset,
+ jint length,
+ jboolean blocking,
+ jintArray address)
+{
+ 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
@@ -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.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 @@
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 static DatagramChannel open(ProtocolFamily family)
}
}
+ 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 int write(ByteBuffer b) throws IOException {
}
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;
}
+ }
- return c;
+ 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();
+ }
+
+ 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 @@ private static native int connect(String hostname, int port)
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;
}
View
@@ -27,15 +27,15 @@ public static void main(String[] args) throws Exception {
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 static void main(String[] args) throws Exception {
case 1: {
if (inKey.isReadable()) {
- in.read(inBuffer);
+ in.receive(inBuffer);
if (! inBuffer.hasRemaining()) {
expect(equal(inBuffer.array(),
inBuffer.arrayOffset(),

0 comments on commit 9974d91

Please sign in to comment.