diff --git a/src/solaris/native/java/net/net_util_md.c b/src/solaris/native/java/net/net_util_md.c index 8a414e60141ba863c6254f06598196a348b887ce..43baab96ea8024d17b45f17ae7a91e3668365e1b 100644 --- a/src/solaris/native/java/net/net_util_md.c +++ b/src/solaris/native/java/net/net_util_md.c @@ -363,17 +363,20 @@ void ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, const char* hostname, int gai_error) { + int size; + char *buf; const char *format = "%s: %s"; const char *error_string = (gai_strerror_ptr == NULL) ? NULL : (*gai_strerror_ptr)(gai_error); if (error_string == NULL) error_string = "unknown error"; - int size = strlen(format) + strlen(hostname) + strlen(error_string) + 2; - char *buf = (char *) malloc(size); + size = strlen(format) + strlen(hostname) + strlen(error_string) + 2; + buf = (char *) malloc(size); if (buf) { + jstring s; sprintf(buf, format, hostname, error_string); - jstring s = JNU_NewStringPlatform(env, buf); + s = JNU_NewStringPlatform(env, buf); if (s != NULL) { jobject x = JNU_NewObjectByName(env, "java/net/UnknownHostException", @@ -1203,19 +1206,26 @@ NET_SetSockOpt(int fd, int level, int opt, const void *arg, } /* - * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris need to - * ensure that value is <= max_buf as otherwise we get - * an invalid argument. + * SOL_SOCKET/{SO_SNDBUF,SO_RCVBUF} - On Solaris we may need to clamp + * the value when it exceeds the system limit. */ #ifdef __solaris__ if (level == SOL_SOCKET) { if (opt == SO_SNDBUF || opt == SO_RCVBUF) { int sotype, arglen; int *bufsize, maxbuf; + int ret; + + /* Attempt with the original size */ + ret = setsockopt(fd, level, opt, arg, len); + if ((ret == 0) || (ret == -1 && errno != ENOBUFS)) + return ret; + + /* Exceeded system limit so clamp and retry */ if (!init_max_buf) { - tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf", 64*1024); - udp_max_buf = getParam("/dev/udp", "udp_max_buf", 64*1024); + tcp_max_buf = getParam("/dev/tcp", "tcp_max_buf", 1024*1024); + udp_max_buf = getParam("/dev/udp", "udp_max_buf", 2048*1024); init_max_buf = 1; } diff --git a/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java b/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java index 54c0b0ea72382973cc9b2a5056c4e5c7ea6807d4..e526112ae2659a02a82e5989e79fab6fc984440a 100644 --- a/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java +++ b/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java @@ -29,7 +29,9 @@ import java.nio.channels.*; import java.net.*; +import static java.net.StandardSocketOption.*; import java.io.IOException; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicReference; @@ -39,6 +41,7 @@ public class Basic { public static void main(String[] args) throws Exception { testBind(); testAccept(); + testSocketOptions(); } static void testBind() throws Exception { @@ -131,4 +134,39 @@ public class Basic { } } + + static void testSocketOptions() throws Exception { + System.out.println("-- socket options --"); + AsynchronousServerSocketChannel ch = AsynchronousServerSocketChannel.open(); + try { + // check supported options + Set> options = ch.supportedOptions(); + if (!options.contains(SO_REUSEADDR)) + throw new RuntimeException("SO_REUSEADDR should be supported"); + if (!options.contains(SO_RCVBUF)) + throw new RuntimeException("SO_RCVBUF should be supported"); + + // allowed to change when not bound + ch.setOption(SO_RCVBUF, 256*1024); // can't check + int before = ch.getOption(SO_RCVBUF); + int after = ch.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF); + if (after < before) + throw new RuntimeException("setOption caused SO_RCVBUF to decrease"); + ch.setOption(SO_REUSEADDR, true); + checkOption(ch, SO_REUSEADDR, true); + ch.setOption(SO_REUSEADDR, false); + checkOption(ch, SO_REUSEADDR, false); + } finally { + ch.close(); + } + } + + static void checkOption(AsynchronousServerSocketChannel ch, + SocketOption name, Object expectedValue) + throws IOException + { + Object value = ch.getOption(name); + if (!value.equals(expectedValue)) + throw new RuntimeException("value not as expected"); + } } diff --git a/test/java/nio/channels/AsynchronousSocketChannel/Basic.java b/test/java/nio/channels/AsynchronousSocketChannel/Basic.java index df12b258ce10e541f5ad0ea19b6561b56b828148..e8f23f46866a4e333b3c68eb771ec3d3b1682591 100644 --- a/test/java/nio/channels/AsynchronousSocketChannel/Basic.java +++ b/test/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -121,8 +121,20 @@ public class Basic { AsynchronousSocketChannel ch = AsynchronousSocketChannel.open() .setOption(SO_RCVBUF, 128*1024) .setOption(SO_SNDBUF, 128*1024) - .setOption(SO_REUSEADDR, true) - .bind(new InetSocketAddress(0)); + .setOption(SO_REUSEADDR, true); + + // check SO_SNDBUF/SO_RCVBUF limits + int before, after; + before = ch.getOption(SO_SNDBUF); + after = ch.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF); + if (after < before) + throw new RuntimeException("setOption caused SO_SNDBUF to decrease"); + before = ch.getOption(SO_RCVBUF); + after = ch.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF); + if (after < before) + throw new RuntimeException("setOption caused SO_RCVBUF to decrease"); + + ch.bind(new InetSocketAddress(0)); // default values if ((Boolean)ch.getOption(SO_KEEPALIVE)) diff --git a/test/java/nio/channels/DatagramChannel/SocketOptionTests.java b/test/java/nio/channels/DatagramChannel/SocketOptionTests.java index cbd6b1468a9f49995cb3cf652a1a14ff5834f0c7..e09fd8c09aaa6d6c49fb355cbf46f2c11db0c64e 100644 --- a/test/java/nio/channels/DatagramChannel/SocketOptionTests.java +++ b/test/java/nio/channels/DatagramChannel/SocketOptionTests.java @@ -68,8 +68,17 @@ public class SocketOptionTests { checkOption(dc, SO_BROADCAST, true); dc.setOption(SO_BROADCAST, false); checkOption(dc, SO_BROADCAST, false); - dc.setOption(SO_SNDBUF, 16*1024); // can't check - dc.setOption(SO_RCVBUF, 16*1024); // can't check + dc.setOption(SO_SNDBUF, 128*1024); // can't check + dc.setOption(SO_RCVBUF, 128*1024); // can't check + int before, after; + before = dc.getOption(SO_SNDBUF); + after = dc.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF); + if (after < before) + throw new RuntimeException("setOption caused SO_SNDBUF to decrease"); + before = dc.getOption(SO_RCVBUF); + after = dc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF); + if (after < before) + throw new RuntimeException("setOption caused SO_RCVBUF to decrease"); dc.setOption(SO_REUSEADDR, true); checkOption(dc, SO_REUSEADDR, true); dc.setOption(SO_REUSEADDR, false); diff --git a/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java b/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java index 8d30e3a18096d17d5dafe745bee82c2c46cf6ae7..d5ad22687d19e6d5107d11a9c2b4573dd0a869dc 100644 --- a/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java +++ b/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java @@ -56,6 +56,10 @@ public class SocketOptionTests { // allowed to change when not bound ssc.setOption(SO_RCVBUF, 256*1024); // can't check + int before = ssc.getOption(SO_RCVBUF); + int after = ssc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF); + if (after < before) + throw new RuntimeException("setOption caused SO_RCVBUF to decrease"); ssc.setOption(SO_REUSEADDR, true); checkOption(ssc, SO_REUSEADDR, true); ssc.setOption(SO_REUSEADDR, false); diff --git a/test/java/nio/channels/SocketChannel/SocketOptionTests.java b/test/java/nio/channels/SocketChannel/SocketOptionTests.java index 89bbfcafc1a1353402e6b2705fad0d5838fa6eaf..9fe1abddef4813a22c1c72ac1501c0ec3558076a 100644 --- a/test/java/nio/channels/SocketChannel/SocketOptionTests.java +++ b/test/java/nio/channels/SocketChannel/SocketOptionTests.java @@ -70,6 +70,15 @@ public class SocketOptionTests { checkOption(sc, SO_KEEPALIVE, false); sc.setOption(SO_SNDBUF, 128*1024); // can't check sc.setOption(SO_RCVBUF, 256*1024); // can't check + int before, after; + before = sc.getOption(SO_SNDBUF); + after = sc.setOption(SO_SNDBUF, Integer.MAX_VALUE).getOption(SO_SNDBUF); + if (after < before) + throw new RuntimeException("setOption caused SO_SNDBUF to decrease"); + before = sc.getOption(SO_RCVBUF); + after = sc.setOption(SO_RCVBUF, Integer.MAX_VALUE).getOption(SO_RCVBUF); + if (after < before) + throw new RuntimeException("setOption caused SO_RCVBUF to decrease"); sc.setOption(SO_REUSEADDR, true); checkOption(sc, SO_REUSEADDR, true); sc.setOption(SO_REUSEADDR, false);