mina-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Emmanuel Lécharny <elecha...@gmail.com>
Subject [MINA 3] SSL working session : a feedback
Date Sun, 05 May 2013 22:23:54 GMT
Hi guys,

we have had a pleasant and useful working session this afternoon with
Jean-François (as we both live in Paris, it was easy for us to meet and
discuss)

Here are a few things we tried to figure out and some of the elements
that need to be further analysed

1) General state machine

The idea is to have one single state machine to handle all the incoming
data : we should not differenciate handshake and non-handshake state
when processing data. The state machine is pretty much the same :
 - we unwrap the data in all cases
 - if the unwrap status is OK, we check the HandshakeStatus (HS), which
gives some indication about what to do next
    - if the HS status is NEED_TASK, we have to execute the task the
SslEngine is returning. It's not something simple to do (see below)
    - if the HS status is UNDERFLOW_BUFFER, we don't have enough data to
proceed an unwrap, and we have to wait for more data. A new select()
will provide some more data.
    - if the HS status is OVERFLOW_BUFFER, that means the application
buffer is not big enough to contain the decrypted data. This is possible
if a compression has been done. We have to create a bigger application
buffer, and redo the unwrap.
    - if the HS status is FINISHED, the handshake is done
    - if the HS status is NOT_HANDSHAKING, that means we already have
handshaken. We can pass the applicatio buffer to the IoHandler.
  - in any case - except for a UNDERFLOW_BUFFER -, if there are more
bytes in the readBuffer, we have to process them

This cover the processing of incoming data.

2) Dealing with UNDERFLOW_BUFFER

We have to read more data, but we must not lose the previous data. The
problem is that the readBuffer is shared with all the sessions, so we
can't do another read withoit potentially losing the dat we already
gathered.

In this case, we need to store the current unprocessed data in a
temporary buffer and when we read some more data, we will add them to
the temporary data.

The algorithm will look like this :

if we have a temporay buffer
  then concatenate the readBuffer in the temporary buffer and go through
the processing of this data

...

if we don't have a BUFFER_UNDERFLOW status
  then reset the temporary buffer

The temporary buffer is associated with the session.

We have an alternative solution : use a buffer associated with every
session. The problem is that it would be wastinga lot of memory (if we
have tens of thousand sessions, we have to keep such a buffer),. Here,
we ust have to allocate a temporary buffer from time to time (see if we
can't pool them).

3) Management of unsent data

Let's say we have pending message waiting to be written (that means the
outbound socket can't accept all the data). If we receive a
renegociation, what should we do with those data ?

We suppose that we should encrypt the data with the newly negotiated
cipher, and not with the previous one. This is quite an issue as the
data are enqueued *after* having been encrypted in the
enqueueWriteRequest() IoSession method.

We have to change the way we process the encyption, in order to differ
the encryption until the last moment (ie when we actually try to write
the data into the socket).

Now, let say we have a queue containing messages to b written : we shoud
not encrypt the newly processed message, we simply add it into the queue.

If on the other hand the queue is empty, we encrypt the message, and try
to send it. If we can't send it completely, we want untli the socket
accept new data. The client SslEngine will be on an
UNDERFLOW_BUFFERuntil the message until the complete message is sent (to
be double checked).

4) NEED_TASK handling

This is a tricky part : the task can be costly, so we should process it
using a different thread. The problem is that once the task is done, we
have to continue the processing when the task is done. At the same time,
we should not accept any incoming data until the task is done, and we
have to emove the OP_READ interest for the session selectionKey. The
thread should also process the next step (which may be a wrap operation,
followed by a write).

We haven't yet found the best solution for that.

5) Close_notify

We still have to see if we are correctly handling this case.

6) Conclusion

Jean-François have a working solution, which probably need some
improvements and checks. This is a first step, and we still have to see
if it works in all the cases (that will need some specific tests).


Jean-François, did I summarized the discussion we had accurately ?

Thanks !

-- 
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com 


Mime
View raw message