[ANN] x0 HTTP server and framework (initial release)

Marc Lehmann schmorp at schmorp.de
Sat Apr 3 17:24:42 CEST 2010

On Sat, Apr 03, 2010 at 04:28:39PM +0200, "common at gmx.ch" <common at gmx.ch> wrote:
> Marc Lehmann wrote:
>> On Thu, Apr 01, 2010 at 10:53:39AM +0200, Graham Leggett <minfrin at sharp.fm> wrote:
>>> You might be tempted to keep two socket watchers going for listening 
>>> to socket read events, and socket write events, but to support SSL  
>> This is the mess how it is commonly implemented, and it is indeed horrors.
> I've had the non-blocking ssl challenge too, and I use two socket  
> watchers, I know it can be done using a single watcher, but ... I'd call  

The mess I was trying to refer to was juggling watcher status depending on
ssl return values, not whether to have one or two watchers.

If you ask me, one or two watchers (or even more) is all fine for me.

But checkign return codes form openssl (want_read/want_write) tends to be
very confusing, and is not necessary, you can drive your watchers in a manner
entirely independent of that openssl return status "mess".

i.e., you can implement ssl purely as a filter between your I/O handling code
(which doesn't need to know about "want_read/write") and the consumer.

> In fact, given the possibility, I use two io watchers for every type of  
> connection, even tcp and udp, and a multitude of timers for each  
> connection type to provide timeouts for all kinds of things I want to be  
> able to deal with (idle, sustain, listen, throtte_(in,out), connecting,  
> dnsresolve, close, handshake, reconnect).
> This makes a total of
>  * 2 io watchers
>  * 10 timers
> -> 12 watchers per connection

That's a lot of timers :)

> I'm totally aware could be done with 2 watchers, one for io, and one  
> timeout and some internal list to have only the 'next' timeout active in  
> libev, but I don't feel bad about it.

Yeah, well the whole point of libev is to handle this for you.

I was thinking for quite some time about a "timerqueue" watcher that would
implement very efficient timers that all have the same timeout value.

That could come handy for all timers of a specific class, without muddling
details too much.

But then, it adds yet another watcher type.

(oh yeah, and an accept watcher...)

> In fact, libev performs that great, I did not even notice a when it had  
> about 6000 connections.

That's good to hear :)

> So, if you don't need the extra tidbit of performance, you can keep  
> things simple.

Yes, definitely, unless you run into real issues, just keep the code simple.

But my plan to reduce all timer operations to O(1) in (some) common cases is
still there :

>> A much easier way is to decouple openssl from the socket altogether,
>> i.e. don't let it do socket I/O, instead let it do I/O from/two two
>> BIO buffers, which simplifies things a lot - no need to watch for
>> SSL_WANT_READ and other issues, no need to switch watcher state based on
>> return codes etc.
> As you have to call SSL_write again with the same arguments again if you  
> get a SSL_WANT_* error, you need two write queues, so you can provide  
> the same arguments.

No, you don't (another common myth). That's just due to an internal check
inside openssl that's not actualyl neede.d You can switch it off by enabling

You still might need two write queues, but these are entirely transparent,
and there is no need to check specifically for SSL_WANT errors at all.

> Proper openssl shutdown was a real problem to me, as it did not work at  
> all, turned out the problem was within openssl, and got patched in 
> 0.9.8m.

Same here :) Of course, it doesn't work all too well with ssl3 in general,
and there is no way to do it with ssl2, but then, those should be dead.

> I was looking at using BIOs myself, but I was not sure about rate  
> limiting when using bios, and there is 'little' examples/documentation,  
> besides some ascii image to illustrate how to design openssl nonblocking  
> with bios.

AFAIK, I am the only one who ever implemented it like this, and I am very
glad I did, as having a transparent ssl "filter" is sooo useful.

> I saw libevent2 providing (rate limited) non-blocking openssl, but I'd  

Oh, fascinating :)

> But example code for (maybe even rate limited?) nonblocking ssl with  
> bios on top of libev would be great.

Well, I gave pseudocode already, and I only did it in perl so far (but the
Net::SSLeay interface is horribly c-ish).

If I write it down, would somebody care to implement and tets it? Would have
a nice place in the docs.

The other issue is of course that I would prefer gnutls over openssl, as
the gnutls license allows redistribution with basically any free software
license, while openssl does not.

Pity that I never used gnutls :()

                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      schmorp at schmorp.de
      -=====/_/_//_/\_,_/ /_/\_\

More information about the libev mailing list