Skip to content

Commit

Permalink
Only call JNI methods if really needed
Browse files Browse the repository at this point in the history
Motivation:

Calling JNI methods is pretty expensive, so we should only do if needed.

Modifications:

Lazy call methods if needed.

Result:

Better performance.
  • Loading branch information
normanmaurer authored and trustin committed Dec 30, 2014
1 parent ea5f389 commit 405cdc8
Showing 1 changed file with 43 additions and 25 deletions.
68 changes: 43 additions & 25 deletions handler/src/main/java/io/netty/handler/ssl/OpenSslEngine.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@ enum ClientAuthMode {
private static final AtomicIntegerFieldUpdater<OpenSslEngine> DESTROYED_UPDATER;
private static final AtomicReferenceFieldUpdater<OpenSslEngine, SSLSession> SESSION_UPDATER;

private static final String INVALID_CIPHER = "SSL_NULL_WITH_NULL_NULL";

// OpenSSL state
private long ssl;
private long networkBIO;
Expand All @@ -133,7 +135,7 @@ enum ClientAuthMode {

// Use an invalid cipherSuite until the handshake is completed
// See http://docs.oracle.com/javase/7/docs/api/javax/net/ssl/SSLEngine.html#getSession()
private volatile String cipher = "SSL_NULL_WITH_NULL_NULL";
private volatile String cipher;
private volatile String applicationProtocol;

// We store this outside of the SslSession so we not need to create an instance during verifyCertificates(...)
Expand Down Expand Up @@ -1007,14 +1009,34 @@ private Principal principal(Certificate[] certs) {

@Override
public String getCipherSuite() {
if (!handshakeFinished) {
return INVALID_CIPHER;
}
if (cipher == null) {
String c = toJavaCipherSuite(SSL.getCipherForSSL(ssl));
if (c != null) {
cipher = c;
}
}
return cipher;
}

@Override
public String getProtocol() {
String applicationProtocol = OpenSslEngine.this.applicationProtocol;
String version = SSL.getVersion(ssl);
if (applicationProtocol == null) {
applicationProtocol = SSL.getNextProtoNegotiated(ssl);
if (applicationProtocol == null) {
applicationProtocol = fallbackApplicationProtocol;
}
if (applicationProtocol != null) {
OpenSslEngine.this.applicationProtocol = applicationProtocol.replace(':', '_');
} else {
OpenSslEngine.this.applicationProtocol = "";
}
}
String version = SSL.getVersion(ssl);
if (applicationProtocol.isEmpty()) {
return version;
} else {
return version + ':' + applicationProtocol;
Expand Down Expand Up @@ -1136,28 +1158,6 @@ public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
// Check to see if we have finished handshaking
if (SSL.isInInit(ssl) == 0) {
handshakeFinished = true;
String c = SSL.getCipherForSSL(ssl);
if (c != null) {
String protocol = toProtocolFamily(SSL.getVersion(ssl));
String converted = CipherSuiteConverter.toJava(c, protocol);
if (converted != null) {
c = converted;
} else {
c = protocol + '_' + c.replace('-', '_');
}
// OpenSSL returns the ciphers seperated by '-' but the JDK SSLEngine does by '_', so replace '-'
// with '_' to match the behaviour.
cipher = c;
}
String applicationProtocol = SSL.getNextProtoNegotiated(ssl);
if (applicationProtocol == null) {
applicationProtocol = fallbackApplicationProtocol;
}
if (applicationProtocol != null) {
this.applicationProtocol = applicationProtocol.replace(':', '_');
} else {
this.applicationProtocol = null;
}
return FINISHED;
}

Expand All @@ -1180,10 +1180,28 @@ public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
return NOT_HANDSHAKING;
}

/**
* Converts the specified OpenSSL cipher suite to the Java cipher suite.
*/
private String toJavaCipherSuite(String openSslCipherSuite) {
if (openSslCipherSuite == null) {
return null;
}

String prefix = toJavaCipherSuitePrefix(SSL.getVersion(ssl));
String converted = CipherSuiteConverter.toJava(openSslCipherSuite, prefix);
if (converted != null) {
openSslCipherSuite = converted;
} else {
openSslCipherSuite = prefix + '_' + openSslCipherSuite.replace('-', '_');
}
return openSslCipherSuite;
}

/**
* Converts the protocol version string returned by {@link SSL#getVersion(long)} to protocol family string.
*/
private static String toProtocolFamily(String protocolVersion) {
private static String toJavaCipherSuitePrefix(String protocolVersion) {
final char c;
if (protocolVersion == null || protocolVersion.length() == 0) {
c = 0;
Expand Down

0 comments on commit 405cdc8

Please sign in to comment.