Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NIO SSL client/server sometimes fails to process data after a handshake #906

Open
jkeljo opened this issue Apr 10, 2014 · 19 comments
Open

Comments

@jkeljo
Copy link
Contributor

jkeljo commented Apr 10, 2014

I've observed this connecting to the NIO SSL server on Android 4.0.4 from Chrome or Postman, however my investigation suggests that the problem is not unique to Android or to the server side.

Typically I'm seeing the first request to a given server succeed, and subsequent requests time out. The difference between successful and failed requests appears to be how the handshake goes:

  • If the last handshake packet is sent by the server to the client, everything is fine
  • If the last handshake packet is sent by the client to the server, and the request is sent quickly, the server will never process the request

The root of the issue is in SslConnection.onFinished. It unconditionally sets the inbound way's ioState to INTEREST, overriding its previous state of READY and causing the Way's buffer processor to break out of the READY loop. If the request had already been read into the buffer, it will simply be left there, unprocessed. It should probably be changed to only set INTEREST if the state is currently IDLE.

Presumably a parallel issue exists for a client's outbound way if the last handshake packet comes from the client, however I haven't reproduced that.

@jkeljo
Copy link
Contributor Author

jkeljo commented Apr 10, 2014

In the connections that succeed, the handshake goes like this:
C: Client Hello
S: Server Hello, Certificate, Server Hello Done
C: Client Key Exchange, Change Cipher Spec, Finished
S: Change Cipher Spec, Finished
C: GET /

In the connections that fail, the handshake goes like this:
C: Client Hello
S: Server Hello, Change Ciper Spec, Finished
C: Change Cipher Spec, Finished
C: GET /

That suggests to me that the server has some memory of the particular client and is short-circuiting the handshake. I'm looking into that further to see if there's a way I can configure restlet to disable that behavior as a workaround.

@jkeljo
Copy link
Contributor Author

jkeljo commented Apr 10, 2014

Failed request log:

W/System.err﹕ OutboundWay#setIoState: IDLE
W/System.err﹕ InboundWay#setIoState: READY
W/System.err﹕ 138 bytes written
W/System.err﹕ 138 bytes drained from buffer at pre-processing, 0 remaining bytes
W/System.err﹕ Ending process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=0, DRAINING, true. Result: 138, try again: true, can loop: false, total filled: 0
W/System.err﹕ Handling SSL result: OK
W/System.err﹕ Handling SSL handshake: NEED_UNWRAP
W/System.err﹕ Outbound way selected. Done for : IDLE, IDLE, java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=0, DRAINING, true
W/System.err﹕ Entering into a connection READY loop
W/System.err﹕ Processing IO for inbound way: READY, START, java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ Beginning process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ 0 bytes drained from buffer at pre-processing, 16384 remaining bytes
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ Beginning process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ 0 bytes drained from buffer at pre-processing, 18437 remaining bytes
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ 517 bytes filled into buffer
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=517 limit=18437, FILLING, false
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=517, DRAINING, false
W/System.err﹕ SSL engine result: SSLEngineReport: Status = OK  HandshakeStatus = NEED_UNWRAP
W/System.err﹕ bytesConsumed = 6 bytesProduced = 0
W/System.err﹕ SSL connection: OPEN | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@4129c138 | null
W/System.err﹕ 6 bytes drained from buffer, 511 remaining bytes
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=6 limit=517, DRAINING, false
W/System.err﹕ SSL engine result: SSLEngineReport: Status = OK  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 53 bytesProduced = 0
W/System.err﹕ SSL connection: OPEN | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@4129c138 | SSLEngineReport: Status = OK  HandshakeStatus = NEED_UNWRAP
W/System.err﹕ bytesConsumed = 6 bytesProduced = 0
W/System.err﹕ 53 bytes drained from buffer, 458 remaining bytes
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=59 limit=517, DRAINING, false
W/System.err﹕ SSL engine result: SSLEngineReport: Status = OK  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 37 bytesProduced = 1
W/System.err﹕ SSL connection: OPEN | false | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@4129c138 | SSLEngineReport: Status = OK  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 53 bytesProduced = 0
W/System.err﹕ 37 bytes drained from buffer, 421 remaining bytes
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=96 limit=517, DRAINING, false
I/dalvikvm﹕ Total arena pages for JIT: 11
I/dalvikvm﹕ Total arena pages for JIT: 12
I/dalvikvm﹕ Total arena pages for JIT: 13
I/dalvikvm﹕ Total arena pages for JIT: 14
I/dalvikvm﹕ Total arena pages for JIT: 15
I/dalvikvm﹕ Total arena pages for JIT: 16
I/dalvikvm﹕ Total arena pages for JIT: 17
W/System.err﹕ SSL engine result: SSLEngineReport: Status = OK  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 421 bytesProduced = 394
W/System.err﹕ SSL connection: OPEN | false | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@4129c138 | SSLEngineReport: Status = OK  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 37 bytesProduced = 1
W/System.err﹕ 421 bytes drained from buffer, 0 remaining bytes
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=517 limit=517, DRAINING, true
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ Ending process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true. Result: 517, try again: false, can loop: true, total filled: 517
W/System.err﹕ Handling SSL result: OK
W/System.err﹕ Handling SSL handshake: NOT_HANDSHAKING
W/System.err﹕ SSLEngine went directly from handshaking to NOT_HANDSHAKING, treating as FINISHED.
W/System.err﹕ InboundWay#setIoState: INTEREST
W/System.err﹕ 517 bytes filled into buffer
W/System.err﹕ Ending process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=395 limit=16384, FILLING, false. Result: 0, try again: true, can loop: false, total filled: 517
W/System.err﹕ Handling SSL result: OK
W/System.err﹕ Handling SSL handshake: NOT_HANDSHAKING
W/System.err﹕ Inbound way selected. Done for : INTEREST, START, java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=395 limit=16384, FILLING, false
W/System.err﹕ helper.control()
W/System.err﹕ controlConnections()
W/System.err﹕ Connection status: CLOSED | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@41291410 | null
W/System.err﹕ InboundWay#clear: IDLE, IDLE, java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ OutboundWay#clear: IDLE, IDLE, java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ InboundWay#clear: IDLE, IDLE, java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ OutboundWay#clear: IDLE, IDLE, java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ Connection status: OPEN | false | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@4129c138 | null
W/System.err﹕ Old connection NIO interest: Interest= READ , Ready=READ , Canceling=false
W/System.err﹕ New connection NIO interest: Interest= READ , Ready=NONE , Canceling=false
W/System.err﹕ registerKeys()
W/System.err﹕ updateKeys()
W/System.err﹕ selectKeys(60000)
W/System.err﹕ NIO controller about to sleep 60000 ms, selecting among 2 keys...

Succeeded request log:

W/System.err﹕ Entering into a connection READY loop
W/System.err﹕ Processing IO for outbound way: READY, IDLE, java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=0, DRAINING, true
W/System.err﹕ Beginning process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=0, DRAINING, true
W/System.err﹕ Beginning process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ 0 bytes drained from buffer at pre-processing, 18437 remaining bytes
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ SSL engine result: SSLEngineReport: Status = OK  HandshakeStatus = NEED_WRAP
W/System.err﹕ bytesConsumed = 0 bytesProduced = 6
W/System.err﹕ SSL connection: OPEN | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@412866e8 | null
W/System.err﹕ 6 bytes filled into buffer
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=6 limit=18437, FILLING, false
W/System.err﹕ SSL engine result: SSLEngineReport: Status = OK  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 0 bytesProduced = 53
W/System.err﹕ SSL connection: OPEN | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@412866e8 | SSLEngineReport: Status = OK  HandshakeStatus = NEED_WRAP
W/System.err﹕ bytesConsumed = 0 bytesProduced = 6
W/System.err﹕ 53 bytes filled into buffer
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=59 limit=18437, FILLING, false
W/System.err﹕ SSL engine result: SSLEngineReport: Status = BUFFER_OVERFLOW  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 0 bytesProduced = 0
W/System.err﹕ SSL connection: OPEN | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@412866e8 | SSLEngineReport: Status = OK  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 0 bytesProduced = 53
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=59, DRAINING, false
W/System.err﹕ 59 bytes drained from buffer, 0 remaining bytes
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=59 limit=59, DRAINING, true
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ SSL engine result: SSLEngineReport: Status = BUFFER_OVERFLOW  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 0 bytesProduced = 0
W/System.err﹕ SSL connection: OPEN | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@412866e8 | SSLEngineReport: Status = BUFFER_OVERFLOW  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 0 bytesProduced = 0
W/System.err﹕ Ending process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true. Result: 59, try again: false, can loop: true, total filled: 59
W/System.err﹕ Handling SSL result: BUFFER_OVERFLOW
W/System.err﹕ SSL buffer overflow state detected. Application buffer needs to be consumed or compacted before retrying.
W/System.err﹕ 59 bytes written
W/System.err﹕ 59 bytes drained from buffer at pre-processing, 0 remaining bytes
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=0, DRAINING, true
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ Ending process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true. Result: 59, try again: false, can loop: true, total filled: 0
W/System.err﹕ Handling SSL result: OK
W/System.err﹕ Handling SSL handshake: NOT_HANDSHAKING
W/System.err﹕ SSLEngine went directly from handshaking to NOT_HANDSHAKING, treating as FINISHED.
W/System.err﹕ InboundWay#setIoState: INTEREST
W/System.err﹕ OutboundWay#setIoState: IDLE
W/System.err﹕ Outbound way selected. Done for : IDLE, IDLE, java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ helper.control()
W/System.err﹕ controlConnections()
W/System.err﹕ Connection status: OPEN | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@412866e8 | null
W/System.err﹕ Old connection NIO interest: Interest= READ , Ready=READ , Canceling=false
W/System.err﹕ New connection NIO interest: Interest= READ , Ready=NONE , Canceling=false
W/System.err﹕ registerKeys()
W/System.err﹕ updateKeys()
W/System.err﹕ selectKeys(60000)
W/System.err﹕ NIO controller about to sleep 60000 ms, selecting among 2 keys...
W/System.err﹕ [ 04-10 07:35:01.718 27864:0x6cf0 W/System.err ]
    NIO controller selected 1 key(s) !
W/System.err﹕ NIO selection detected for key: Interest= READ , Ready=NONE , Canceling=false
W/System.err﹕ Server connection (state | empty | registration): OPEN | true | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@412866e8 | null
W/System.err﹕ InboundWay#setIoState: PROCESSING
W/System.err﹕ Processing IO for inbound way: PROCESSING, START, java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ Beginning process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ 0 bytes drained from buffer at pre-processing, 16384 remaining bytes
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=16384, FILLING, true
W/System.err﹕ Beginning process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ 0 bytes drained from buffer at pre-processing, 18437 remaining bytes
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ 458 bytes filled into buffer
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=458 limit=18437, FILLING, false
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=458, DRAINING, false
W/System.err﹕ SSL engine result: SSLEngineReport: Status = OK  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 37 bytesProduced = 1
W/System.err﹕ SSL connection: OPEN | false | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@412866e8 | null
W/System.err﹕ 37 bytes drained from buffer, 421 remaining bytes
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=37 limit=458, DRAINING, false
W/System.err﹕ SSL engine result: SSLEngineReport: Status = OK  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 421 bytesProduced = 394
W/System.err﹕ SSL connection: OPEN | false | Interest= READ , Ready=READ , Canceling=false | org.apache.harmony.xnet.provider.jsse.SSLEngineImpl@412866e8 | SSLEngineReport: Status = OK  HandshakeStatus = NOT_HANDSHAKING
W/System.err﹕ bytesConsumed = 37 bytesProduced = 1
W/System.err﹕ 421 bytes drained from buffer, 0 remaining bytes
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=458 limit=458, DRAINING, true
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ Ending process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true. Result: 458, try again: false, can loop: true, total filled: 458
W/System.err﹕ Handling SSL result: OK
W/System.err﹕ Handling SSL handshake: NOT_HANDSHAKING
W/System.err﹕ 458 bytes filled into buffer
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=395 limit=16384, FILLING, false
W/System.err﹕ Beginning process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ 0 bytes drained from buffer at pre-processing, 18437 remaining bytes
W/System.err﹕ Filling buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true
W/System.err﹕ Ending process of buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=18437 position=0 limit=18437, FILLING, true. Result: 0, try again: false, can loop: true, total filled: 0
W/System.err﹕ Handling SSL result: OK
W/System.err﹕ Handling SSL handshake: NOT_HANDSHAKING
W/System.err﹕ Draining buffer java.nio.ReadWriteHeapByteBuffer, status: capacity=16384 position=0 limit=395, DRAINING, false
W/System.err﹕ GET / HTTP/1.1

@jkeljo
Copy link
Contributor Author

jkeljo commented Apr 10, 2014

I verified with Wireshark that there is SSL session reuse going on and that's what's causing the different handshake behavior.

Tried setting a very short timeout on the SSLSessionContext returned by SSLContext.getServerSessionContext. However, on Android 4.0.4 that appears to not be sufficient. I suspect OpenSSL has its own cache underneath that is not affected by this call.

@jkeljo
Copy link
Contributor Author

jkeljo commented Apr 10, 2014

Further confirmation and an ugly workaround:

I inherited from HttpsServerHelper and overrode getSslContext to return a new SSLContext with each call. It seriously slows down startup and creates a ton of contexts, but it does prevent session reuse and thus prevents this bug from reproducing. At least for a while...who knows what happens when we recycle a connection from the pool. It'll get me by for a bit, anyway.

@jlouvel jlouvel added this to the 2.2.1 milestone Apr 11, 2014
@jlouvel jlouvel modified the milestones: 2.2.2, 2.2.1 Apr 30, 2014
@jlouvel
Copy link
Member

jlouvel commented May 2, 2014

Thanks Jonathan for the investigation. We'll try to look into this for V2.2.2

@jlouvel jlouvel modified the milestones: 2.2.2, 2.2.3, 2.3 M4, 2.x - Maintenance Oct 24, 2014
@jlouvel jlouvel added this to the Unplanned milestone Nov 2, 2014
@jlouvel jlouvel added this to the Unplanned milestone Nov 2, 2014
@lotto99
Copy link

lotto99 commented Mar 19, 2015

Hello,
it seems like we have similar/same problem.
We have this topology:
CLIENT (IBM ESB) -rest call-> LOAD BALANCER -routes to-> HTTP SERVER (IBM IHS) -invokes process-> IBM BPM

Between client and LB we tracked this log:
10:01:12 search, 10:01:13 assign, 10:01:14 finish
10:01:46 search, 10:01:47 assign, 10:01:47 finish (failed)
10:05:30 search...

Then client times-out:

[3/13/15 10:05:31:006 CET] 00000005 TimeoutManage I   WTRN0124I: When the timeout occurred the thread with which the transaction is, or was most recently, associated was Thread[WebContainer : 0,5,main]. The stack trace of this thread when the timeout occurred was:
        sun.misc.Unsafe.park(Native Method)
        java.util.concurrent.locks.LockSupport.park(LockSupport.java:182)
        java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:822)
        java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(AbstractQueuedSynchronizer.java:980)
        java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(AbstractQueuedSynchronizer.java:1292)
        java.util.concurrent.CountDownLatch.await(CountDownLatch.java:218)
        org.restlet.engine.connector.ClientConnectionHelper.handle(ClientConnectionHelper.java:445)
        org.restlet.Client.handle(Client.java:180)
        org.restlet.Restlet.handle(Restlet.java:284)

According our analysis, very likely the handshake has been done, but the message wasn't sent.
I hoped this will be fixed as stated above in 2.2.2, but I din't find it there.
p.s. we are on the 2.1.7 libraries and are limited to Java 1.6

Many thanks for any help.

@jlouvel
Copy link
Member

jlouvel commented Mar 20, 2015

@lotto99 Could you add the org.restlet.ext.net.jar library to your classpath to replace the internal HTTP client? That should help workaround the issue

@lotto99
Copy link

lotto99 commented Apr 28, 2015

Hello Jerome,
I am back by this problem. Yes I checked the library path, and according system output below, the client is negotiating the handshake obviously from restlet lib (not some internal http client):

[4/28/15 14:46:35:386 CEST] 00000128 restlet       I   Starting the internal [HTTPS/1.1] client
[4/28/15 14:47:35:438 CEST] 00000128 RestClientBas E   HTTP response:
Response status: Error while processing a connection
Response status code: 1001
Response phrase: Communication Error
Response: Communication Error (1001) - Error while processing a connection
[4/28/15 14:47:35:440 CEST] 00000128 RestClientBas E
Exception info:
Exception message: Connection reset by peer
[4/28/15 14:47:35:441 CEST] 00000128 RestClientBas E   Exception stack trace:
                                 java.io.IOException: Connection reset by peer
        at sun.nio.ch.FileDispatcher.read0(Native Method)
        at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:33)
        at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:210)
        at sun.nio.ch.IOUtil.read(IOUtil.java:183)
        at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:257)
        at org.restlet.engine.io.ReadableSocketChannel.read(ReadableSocketChannel.java:82)
        at org.restlet.engine.connector.Connection$1.read(Connection.java:232)
        at org.restlet.engine.io.Buffer.fill(Buffer.java:395)

Additionaly, the problem is not present in 100% of communication, but only about 50% of handshakes fail..I observed the timeout problem by PUT and POST methods (but this is probably irrelevant in relation to handshake).

Since this is getting quite critical problem for us, is there any plan to make some fix about this (maybe something as jkeljo mentioned)? You mentioned release 2.2.2...

Or you have any hint to make progress in my case? I can try to get TCP dump if necessary.
Thanks for any help.

@lotto99
Copy link

lotto99 commented Apr 28, 2015

My Client is used such way:

httpClient = new org.restlet.Client(ctx, protocol);
Response response = httpClient.handle(request);

Should I try the org.restlet.ext.net.HttpClientHelper as you mentioned this library? I didn't find any tutorial to this..

@thboileau
Copy link
Contributor

Hello @lotto99 , if you want to try this you just to update the classpath of your jvm with:

  • the org.restlet.ext.httpclient.jar file
  • and its dependencies:
    • org.apache.commons.codec v1.5
    • org.apache.httpclient v4.3
    • org.apache.httpcore v4.3
    • org.apache.httpmime v4.3
    • org.apache.james.mime4j v0.7
    • org.apache.commons.logging v1.1

If you have downloaded the framework via the zip file, these dependencies are shipped in the libraries directory.

@lotto99
Copy link

lotto99 commented Jun 9, 2015

Hello Restlet guys,
I successfully solved the "unstable conection" problem with your help.
Hopefully it helps somebody else. Thanks for help.

I used it like this:
HttpClientHelper httpClientHelper = new HttpClientHelper(new Client(ctx, protocol));
// Ask the HTTP client connector to handle the call
Response response = new ClientResource(url).getResponse();
httpClientHelper.handle(request, response);

Additionaly, it needed the import of server certificate to the client java, because the rest call was via https.

@amitchaturvedi
Copy link

Hi @jlouvel & @thboileau ,

When will you fix this issue as this has already been pending since long? Please fix it ASAP as this is creating major blocking for us.

Hi @jkeljo ,

Could you please help us to understand the workaround provided by you ? I am using Android 5.0.
If I use very short timeout on the SSLSessionContext returned by SSLContext.getServerSessionContext. Will it solve the problem for Android 5.0?

or I have to return a new SSLContext with each call as you mentioned above. Could you please share the source code for the same, if possible? Request you to please help me to fix this issue.

Do we have any other workaround where we can change the IO state accordingly to fix this issue?

Regards,
Amit

@amitchaturvedi
Copy link

Hello @jlouvel & @thboileau,

Waiting for your response on the above issue. Please help me solve this issue as it is a major obstacle for us.

Regards,
Amit

@jlouvel
Copy link
Member

jlouvel commented Oct 21, 2015

@amitchaturvedi The workaround consist in using the Apache HTTP extension of Restlet (org.restlet.ext.httpclient.jar basically) but you can also use the (org.restlet.ext.net one based on HttpURLConnection's class from JRE.

The NIO issue lies in the custom/internal HTTP implementation that we had developed in V2.1 directly based on NIO that is very difficilut to fix and stabilize. Moving forward (V3 and beyond), we have decided to rely on Netty NIO library instead.

Sorry for the trouble. Let us know if you need further help.

@amitchaturvedi
Copy link

@jlouvel thank you for your prompt reply. As I understood, the problem is with SSL Session Reuse. Could you please suggest, if somehow we can disable the Session Reuse option by configuring some restlet parameters and can fix the issue.

Or some other alternative. Actually we have an immediate release and changing the complete design based on some other framework will not be possible at this point of time.

I am sure that you can suggest something which will definitely help me to avoid this situation. The workaround which is provided by @jkeljo may also help . Could you please suggest me how to implement this ?

Regards,
Amit

@jlouvel
Copy link
Member

jlouvel commented Oct 21, 2015

The suggestion of changing the HTTP connector used by your Restlet client app doesn't require changing your design or code.

Basically, you need to add the org.restlet.net.jar file to your Android project and manually register it with the Restlet Engine using Engine.getInstance().getRegisteredClients().add(0, new org.restlet.net.HttpClientHelper(null)).

See additional help here:
http://stackoverflow.com/questions/12992282/which-restlet-https-client-to-use-on-android

@amitchaturvedi
Copy link

Hi @jlouvel , I don't have any Restlet Client App. I have Restlet Server App which runs on Android 5.0.

I have also a Client App which is not based on Restlet. When this App communicates with my Restlet server, I can observe that most of the requests get timed out. I have also taken the wireshark logs. This issue is same as what @jkeljo has defined in the first 3 comments.

Will the suggestion provided by you work with Restlet Server App also ?

Please confirm.

@jlouvel
Copy link
Member

jlouvel commented Oct 21, 2015

For Android HTTP server, this is going to be more difficult unfortunately.
There is no Restlet server alternative.

Your best bet, would be to use the i-Jetty port of Jetty for Android:
https://github.com/jetty-project/i-jetty

and then, to adapt our Restlet/Jetty server connector code to work with it:
https://github.com/restlet/restlet-framework-java/tree/2.1/modules/org.restlet.ext.jetty

I can provide assistance if you undertake this coding effort.

@amitchaturvedi
Copy link

Hi @jlouvel I have few queries regarding the Android HTTP Restlet Server and request you to share your views on the same :

  1. Are we planning to port i-jetty on Restlet ? If yes, then what is the plan.? I am also interested to contribute in this. Please let me know how can I provide my support in this .
  2. Now the Restlet extension also includes JAX-RS (in Restlet 2.2 & later version). May I know how it is different from the earlier version . I mean I can initialize my Restlet server by using JAX-RS extension but what is the benefit of using this JAX-RS in Restlet ( in terms of Stability and performance not protocol).?
  3. Is JAX-RS extension supports Resteasy and Jersey both or only one of them?
  4. In the link below, I have found the details of JaxRs
    https://restlet.com/technical-resources/restlet-framework/guide/2.3/extensions/jaxrs
    The link does not say that it requires org,restlet.ext.nio. I have used the same example provided in the link above. I have used the Android version of JARS. I have found that I have to include the following in my code to run my Restlet server otherwise Restler server does not work

Engine.getInstance().getRegisteredServers().add(new HttpServerHelper(null));

And the HttpServerHelper is available in import org.restlet.ext.nio.HttpServerHelper.

May I know if the NIO is required to run the Restlet server, in case i am using Restlet JAX-RS extension to configure and run my Restlet server ?

Thanking you in Advance.

Regards,
Amit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants