Repository: netty/netty
Issue: OpenSslContext throws UnsupportedOperationException when Unsafe not available 
Labels: defect

Netty 4.0.34.Final on OS X, Unsafe not available due to SecurityManager and restrictive policy file.

So this warning is issued: "[io.netty.util.internal.PlatformDependent] Your platform does not provide complete low-level API for accessing direct buffers reliably. Unless explicitly requested, heap buffer will always be preferred to avoid potential system unstability."

OpenSslContext constructor fails with a UnsupportedOperationException because in OpenSslContext.java:542 "UnpooledDirectByteBuf.memoryAddress()" is not supported.

<pre>
Caused by: java.lang.UnsupportedOperationException
    at io.netty.buffer.UnpooledDirectByteBuf.memoryAddress(UnpooledDirectByteBuf.java:210)
    at io.netty.handler.ssl.OpenSslContext.newBIO(OpenSslContext.java:542)
    at io.netty.handler.ssl.OpenSslContext.toBIO(OpenSslContext.java:533)
    at io.netty.handler.ssl.OpenSslClientContext.<init>(OpenSslClientContext.java:289)
</pre>


Issue comments:
@floragunncom which java version and java brand ?

Oracle 1.8.0_45 on Mac OS Yosemite

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

I need to create a new Open SSL Engine and i do it with:

<pre>
sslContext.newEngine(PooledByteBufAllocator.DEFAULT);
</pre>

Maybe this is the flaw?

@floragunncom that said I think we should use JDK provider if Unsafe is not present. I will come up with a patch

@floragunncom actually I think we not need unsafe for OpenSsl. Working on a fix

Fixed...


Pull request review comments:

Patch that resolved the issue:
diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java b/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java
index 619768aa67a..4b67ead89fc 100644
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java
+++ b/handler/src/main/java/io/netty/handler/ssl/OpenSsl.java
@@ -16,9 +16,11 @@
 
 package io.netty.handler.ssl;
 
+import io.netty.buffer.ByteBuf;
 import io.netty.util.internal.NativeLibraryLoader;
 import io.netty.util.internal.logging.InternalLogger;
 import io.netty.util.internal.logging.InternalLoggerFactory;
+import org.apache.tomcat.jni.Buffer;
 import org.apache.tomcat.jni.Library;
 import org.apache.tomcat.jni.Pool;
 import org.apache.tomcat.jni.SSL;
@@ -190,5 +192,10 @@ static boolean isError(long errorCode) {
         return errorCode != SSL.SSL_ERROR_NONE;
     }
 
+    static long memoryAddress(ByteBuf buf) {
+        assert buf.isDirect();
+        return buf.hasMemoryAddress() ? buf.memoryAddress() : Buffer.address(buf.nioBuffer());
+    }
+
     private OpenSsl() { }
 }
diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java
index 22b74f2179a..8b3c7ea656f 100644
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java
+++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslContext.java
@@ -544,7 +544,7 @@ static long toBIO(X509Certificate[] certChain) throws Exception {
     private static long newBIO(ByteBuf buffer) throws Exception {
         long bio = SSL.newMemBIO();
         int readable = buffer.readableBytes();
-        if (SSL.writeToBIO(bio, buffer.memoryAddress(), readable) != readable) {
+        if (SSL.writeToBIO(bio, OpenSsl.memoryAddress(buffer), readable) != readable) {
             SSL.freeBIO(bio);
             throw new IllegalStateException("Could not write data to memory BIO");
         }
diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java
index 420581661da..a55b9c8c1c5 100644
--- a/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java
+++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java
@@ -52,6 +52,7 @@
 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 
 import static io.netty.handler.ssl.ApplicationProtocolConfig.SelectedListenerFailureBehavior;
+import static io.netty.handler.ssl.OpenSsl.memoryAddress;
 import static io.netty.util.internal.ObjectUtil.checkNotNull;
 import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*;
 import static javax.net.ssl.SSLEngineResult.Status.*;
@@ -1235,14 +1236,6 @@ private HandshakeStatus handshake() throws SSLException {
         return FINISHED;
     }
 
-    private static long memoryAddress(ByteBuf buf) {
-        if (buf.hasMemoryAddress()) {
-            return buf.memoryAddress();
-        } else {
-            return Buffer.address(buf.nioBuffer());
-        }
-    }
-
     private SSLEngineResult.Status getEngineStatus() {
         return engineClosed? CLOSED : OK;
     }


Test patch: