diff --git a/classpath/java-net.cpp b/classpath/java-net.cpp new file mode 100644 index 0000000000..bd94f3e52c --- /dev/null +++ b/classpath/java-net.cpp @@ -0,0 +1,76 @@ +/* Copyright (c) 2010, 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. */ + +#include "jni.h" +#include "jni-util.h" + +#ifdef PLATFORM_WINDOWS +# include +# define ONLY_ON_WINDOWS(x) x +#else +# include +# define ONLY_ON_WINDOWS(x) +#endif + +extern "C" JNIEXPORT void JNICALL +Java_java_net_Socket_init(JNIEnv* ONLY_ON_WINDOWS(e), jclass) +{ +#ifdef PLATFORM_WINDOWS + static bool wsaInitialized = false; + if (not wsaInitialized) { + WSADATA data; + int r = WSAStartup(MAKEWORD(2, 2), &data); + if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) { + throwNew(e, "java/io/IOException", "WSAStartup failed"); + } + } +#endif +} + +extern "C" JNIEXPORT jint JNICALL +Java_java_net_InetAddress_ipv4AddressForName(JNIEnv* e, + jclass, + jstring name) +{ + const char* chars = e->GetStringUTFChars(name, 0); + if (chars) { +#ifdef PLATFORM_WINDOWS + hostent* host = gethostbyname(chars); + e->ReleaseStringUTFChars(name, chars); + if (host) { + return htonl(reinterpret_cast(host->h_addr_list[0])->s_addr); + } else { + fprintf(stderr, "trouble %d\n", WSAGetLastError()); + } +#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(name, chars); + + jint address; + if (r != 0) { + address = 0; + } else { + address = htonl + (reinterpret_cast(result->ai_addr)->sin_addr.s_addr); + + freeaddrinfo(result); + } + + return address; +#endif + } + return 0; +} diff --git a/classpath/java-nio.cpp b/classpath/java-nio.cpp index b8a2222bcb..25d2d673b0 100644 --- a/classpath/java-nio.cpp +++ b/classpath/java-nio.cpp @@ -18,6 +18,7 @@ #ifdef PLATFORM_WINDOWS # include +# include # include # ifdef _MSC_VER # define snprintf sprintf_s @@ -150,20 +151,40 @@ init(JNIEnv* e, sockaddr_in* address, jstring hostString, jint port) { const char* chars = e->GetStringUTFChars(hostString, 0); if (chars) { +#ifdef PLATFORM_WINDOWS hostent* host = gethostbyname(chars); e->ReleaseStringUTFChars(hostString, chars); if (host == 0) { -#ifdef PLATFORM_WINDOWS throwIOException(e); -#else - throwIOException(e, hstrerror(h_errno)); -#endif return; } + memset(address, 0, sizeof(sockaddr_in)); address->sin_family = AF_INET; address->sin_port = htons(port); address->sin_addr = *reinterpret_cast(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 + (result->ai_addr)->sin_addr; + + freeaddrinfo(result); +#endif } } @@ -328,17 +349,6 @@ doWrite(int fd, const void* buffer, size_t count) int makeSocket(JNIEnv* e) { -#ifdef PLATFORM_WINDOWS - static bool wsaInitialized = false; - if (not wsaInitialized) { - WSADATA data; - int r = WSAStartup(MAKEWORD(2, 2), &data); - if (r or LOBYTE(data.wVersion) != 2 or HIBYTE(data.wVersion) != 2) { - throwIOException(e, "WSAStartup failed"); - } - } -#endif - int s = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (s < 0) { throwIOException(e); diff --git a/classpath/java/net/InetAddress.java b/classpath/java/net/InetAddress.java new file mode 100644 index 0000000000..3f49a9b739 --- /dev/null +++ b/classpath/java/net/InetAddress.java @@ -0,0 +1,53 @@ +/* Copyright (c) 2010, 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 class InetAddress { + private final String address; + + private InetAddress(String address) { + this.address = address; + } + + public String getHostAddress() { + return address; + } + + public static InetAddress getByName(String name) + throws UnknownHostException + { + try { + Socket.init(); + } 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)); + } + + private static native int ipv4AddressForName(String name); +} diff --git a/classpath/java/net/Socket.java b/classpath/java/net/Socket.java index 602b24a19e..9fbc1e4523 100644 --- a/classpath/java/net/Socket.java +++ b/classpath/java/net/Socket.java @@ -10,6 +10,10 @@ package java.net; +import java.io.IOException; + public abstract class Socket { + public static native void init() throws IOException; + public abstract void setTcpNoDelay(boolean on) throws SocketException; } diff --git a/classpath/java/net/UnknownHostException.java b/classpath/java/net/UnknownHostException.java new file mode 100644 index 0000000000..85e4da0eac --- /dev/null +++ b/classpath/java/net/UnknownHostException.java @@ -0,0 +1,21 @@ +/* Copyright (c) 2010, 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 class UnknownHostException extends IOException { + public UnknownHostException(String host) { + super(host); + } + + public UnknownHostException() { } +} diff --git a/classpath/java/nio/channels/Selector.java b/classpath/java/nio/channels/Selector.java index 2354859cb0..942357c773 100644 --- a/classpath/java/nio/channels/Selector.java +++ b/classpath/java/nio/channels/Selector.java @@ -18,7 +18,7 @@ public abstract class Selector { protected final Set keys = new HashSet(); protected final Set selectedKeys = new HashSet(); - public static Selector open() { + public static Selector open() throws IOException { return new SocketSelector(); } diff --git a/classpath/java/nio/channels/ServerSocketChannel.java b/classpath/java/nio/channels/ServerSocketChannel.java index 0bb135c3e9..c8a691c5c5 100644 --- a/classpath/java/nio/channels/ServerSocketChannel.java +++ b/classpath/java/nio/channels/ServerSocketChannel.java @@ -15,11 +15,16 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.net.ServerSocket; +import java.net.Socket; public class ServerSocketChannel extends SelectableChannel { - private final SocketChannel channel = new SocketChannel(); + private final SocketChannel channel; - public static ServerSocketChannel open() { + private ServerSocketChannel() throws IOException { + channel = new SocketChannel(); + } + + public static ServerSocketChannel open() throws IOException { return new ServerSocketChannel(); } @@ -58,6 +63,8 @@ public class ServerSocketChannel extends SelectableChannel { } private int doListen(String host, int port) throws IOException { + Socket.init(); + return natDoListen(host, port); } diff --git a/classpath/java/nio/channels/SocketChannel.java b/classpath/java/nio/channels/SocketChannel.java index 25da62684c..db20896f1c 100644 --- a/classpath/java/nio/channels/SocketChannel.java +++ b/classpath/java/nio/channels/SocketChannel.java @@ -26,7 +26,9 @@ public class SocketChannel extends SelectableChannel boolean connected = false; boolean blocking = true; - public static SocketChannel open() { + public static SocketChannel open() throws IOException { + Socket.init(); + return new SocketChannel(); } diff --git a/classpath/java/nio/channels/SocketSelector.java b/classpath/java/nio/channels/SocketSelector.java index 7ad46b5355..8ad7bbafd8 100644 --- a/classpath/java/nio/channels/SocketSelector.java +++ b/classpath/java/nio/channels/SocketSelector.java @@ -12,13 +12,16 @@ package java.nio.channels; import java.io.IOException; import java.util.Iterator; +import java.net.Socket; class SocketSelector extends Selector { protected long state; protected final Object lock = new Object(); protected boolean woken = false; - public SocketSelector() { + public SocketSelector() throws IOException { + Socket.init(); + state = natInit(); }