Assorted socket fixes related to test_SSLSocket_setSoWriteTimeout failure investigation
1.) Fixed the failure of libcore.javax.net.ssl.SSLSocketTest's
test_SSLSocket_setSoWriteTimeout by setting send/recv buffer sizes earlier (b/8272932)
2.) Fixed javadoc bug in java.net.Socket
3.) Fixed implementation bug in IoBridge affecting reading SO_RCVBUF
4.) Fixed bug where we would leave unsent bytes in OpenSSL write buffer after SSLSocket write
possible cause of b/6693087
Bug: 8272932
Bug: 6693087
Change-Id: I54e084e58e8b10583a6ac3051d5e05e519139d64
diff --git a/luni/src/main/java/java/net/Socket.java b/luni/src/main/java/java/net/Socket.java
index a9e0bc3..2d80586 100644
--- a/luni/src/main/java/java/net/Socket.java
+++ b/luni/src/main/java/java/net/Socket.java
@@ -482,7 +482,7 @@
}
/**
- * Sets this socket's {@link SocketOptions#SO_SNDBUF receive buffer size}.
+ * Sets this socket's {@link SocketOptions#SO_RCVBUF receive buffer size}.
*/
public synchronized void setReceiveBufferSize(int size) throws SocketException {
checkOpenAndCreate(true);
diff --git a/luni/src/main/java/libcore/io/IoBridge.java b/luni/src/main/java/libcore/io/IoBridge.java
index afb4146..f2f60db 100644
--- a/luni/src/main/java/libcore/io/IoBridge.java
+++ b/luni/src/main/java/libcore/io/IoBridge.java
@@ -273,7 +273,7 @@
case SocketOptions.SO_OOBINLINE:
return booleanFromInt(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_OOBINLINE));
case SocketOptions.SO_RCVBUF:
- return Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_SNDBUF);
+ return Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_RCVBUF);
case SocketOptions.SO_REUSEADDR:
return booleanFromInt(Libcore.os.getsockoptInt(fd, SOL_SOCKET, SO_REUSEADDR));
case SocketOptions.SO_SNDBUF:
diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
index aafba3a..9991fc4 100644
--- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
+++ b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
@@ -7344,7 +7344,7 @@
int count = len;
- while (appData->aliveAndKicking && len > 0) {
+ while (appData->aliveAndKicking && ((len > 0) || (ssl->s3->wbuf.left > 0))) {
errno = 0;
if (MUTEX_LOCK(appData->mutex) == -1) {
@@ -7353,11 +7353,11 @@
unsigned int bytesMoved = BIO_number_read(bio) + BIO_number_written(bio);
- // ALOGD("Doing SSL_write() with %d bytes to go", len);
if (!appData->setCallbackState(env, shc, fdObject, NULL)) {
MUTEX_UNLOCK(appData->mutex);
return THROWN_EXCEPTION;
}
+ JNI_TRACE("ssl=%p sslWrite SSL_write len=%d left=%d", ssl, len, ssl->s3->wbuf.left);
int result = SSL_write(ssl, buf, len);
appData->clearCallbackState();
// callbacks can happen if server requests renegotiation
@@ -7371,7 +7371,8 @@
sslError = SSL_get_error(ssl, result);
freeOpenSslErrorState();
}
- JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d", ssl, result, sslError);
+ JNI_TRACE("ssl=%p sslWrite SSL_write result=%d sslError=%d left=%d",
+ ssl, result, sslError, ssl->s3->wbuf.left);
#ifdef WITH_JNI_TRACE_DATA
for (int i = 0; i < result; i+= WITH_JNI_TRACE_DATA_CHUNK_SIZE) {
int n = std::min(result - i, WITH_JNI_TRACE_DATA_CHUNK_SIZE);
diff --git a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
index 331b981..7ce8727 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/SSLSocketTest.java
@@ -20,6 +20,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
+import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
@@ -45,7 +46,6 @@
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLProtocolException;
-import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
@@ -1114,8 +1114,27 @@
}
final TestSSLContext c = TestSSLContext.create();
- SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host,
- c.port);
+ SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
+
+ // Try to make the client SO_SNDBUF size as small as possible
+ // (it can default to 512k or even megabytes). Note that
+ // socket(7) says that the kernel will double the request to
+ // leave room for its own book keeping and that the minimal
+ // value will be 2048. Also note that tcp(7) says the value
+ // needs to be set before connect(2).
+ int sendBufferSize = 1024;
+ client.setSendBufferSize(sendBufferSize);
+ sendBufferSize = client.getSendBufferSize();
+
+ // In jb-mr2 it was found that we need to also set SO_RCVBUF
+ // to a minimal size or the write would not block. While
+ // tcp(2) says the value has to be set before listen(2), it
+ // seems fine to set it before accept(2).
+ final int recvBufferSize = 128;
+ c.serverSocket.setReceiveBufferSize(recvBufferSize);
+
+ client.connect(new InetSocketAddress(c.host, c.port));
+
final SSLSocket server = (SSLSocket) c.serverSocket.accept();
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> future = executor.submit(new Callable<Void>() {
@@ -1135,14 +1154,12 @@
new Class[] { Integer.TYPE });
setSoWriteTimeout.invoke(client, 1);
- // Try to make the size smaller (it can be 512k or even megabytes).
- // Note that it may not respect your request, so read back the actual value.
- int sendBufferSize = 1024;
- client.setSendBufferSize(sendBufferSize);
- sendBufferSize = client.getSendBufferSize();
try {
- client.getOutputStream().write(new byte[sendBufferSize + 1]);
+ // Add extra space to the write to exceed the send buffer
+ // size and cause the write to block.
+ final int extra = 1;
+ client.getOutputStream().write(new byte[sendBufferSize + extra]);
fail();
} catch (SocketTimeoutException expected) {
}