Mark Williams wrote: > > 2) Let the two threads read and write to your own two > > independent queues and > > service the application side of the SSL connection with your > > own code to and from the read and write queues.
> Won't I still need to combine the reading and writing to the SSL object > into a > single thread for this? This is the bit I am having difficulty > visualising. The data pump thread is more or less like this: While (connection_is_alive) { If (connection_is_not_corked_in) { SSL_read into temporary buffer. If we got data: { If a read thread is blocked, unblock it. If the receive queue is too full, set the 'corked_in' flag. } If we got a fatal error, mark the connection dead. } If(send queue not empty) { Try to send some data using SSL_write Put back what we didn't send } If we made no forward progress, block (see notes) } Tear down the connection The read thread acquires the queue mutex, blocks on the condvar for data if desired, pulls data off the queue, and clears the corked_in flag if it was set (assuming the queue is still not full), and signals the data pump thread if it uncorked. The write thread acquires the mutex, checks if the send queue is full, blocks on the condvar if it is, and signals the data pump thread if the queu was empty. The only trick left is the blocking logic in the data pump thread. This is the hard part: 1) If you have no outbound data pending, and the connection is corked, block only on an internal signal. (Since you don't want to do I/O either way anyway.) 2) If you have outbound data pending and the connection is corked, block as directed by SSL_write. If it said WANT_READ, block on read. If it said WANT_WRITE, block on write. 3) If you have no outbound data pending (and hence, did not call SSL_write), and the connection is uncorked, block as directed in SSL_read. 4) If you have outbound data pending, and the connection is uncorked, block on the logical OR of the SSL_read result and the SSL_write result (block for read on the socket if either one returned WANT_READ, block for write if either returned WANT_WRITE). Note that your data pump threads needs to block on a 'select' or 'poll' type function but be unblocked when signaled. If necessary, add one end of a pipe to the select/poll set and have you read/write threads write a byte to that pipe to unblock the data pump thread. This is from memory, but it should be basically correct. By the way, I think only the logic in 4 is not obviously correct. Here's the proof it's safe: 1) If nothing changed, and we block on the OR of both operations, we will only unblock if one of those operations can make forward progress. (We only unblock on X if one operation Xould make forward progress on X, and nothing has changed since then.) 2) If something changed, then we already made some forward progress. So either way, we make forward progress in each pass of the loop, which is the best you can hope for. DS ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List openssl-users@openssl.org Automated List Manager majord...@openssl.org