Hello list, I wrote a library (GPL) that aims for not creating more threads than CPU cores. This library provides a thread pool and does all timer and socket/filedescriptor monitoring.
At the moment I can create a TCP connection and read/write data in a 100% non-blocking way by means of callback functions (well, not really - but that would be the same); when it is possible to write data and I have data, a function is called that allows me to do that: write the data. When a socket has data then a function is called that allows me to read that data. I now wish to add TLS layer to this. In order to (still) never put a thread to sleep (except a specialized one that does the calls to epoll) I need this gnutls to provided the following interface: it should call a callback function (that I configured) to tell me that it is interested in reading and/or writing (not to get actual data or write it - just to tell me that it is ready to do so). When there is nothing to do for the library, it should return from whatever function I called (it should never go to sleep internally, or internally wait for anything (like sockets or a timer)). When the library indicates it is interested in reading or writing data, I will call functions of the library as soon as this is possible; ie, when the library wants to read I can provide it a non-blocking fd that it can read from, or I can do reading and buffering myself and call a function of the library providing a buffer pointer and the number of characters available in the buffer. [ Ideal would be when the gnutls also provided an end-of-message detection function that I could use to know when I have a complete message, so that my library can provide strictly contiguous messages, but this is not absolutely necessary (the result I'd expect is that the library will make a copy of the data that I provide; which is slower, but that is ok I suppose). If each message always starts with a header that contains the total length of that message then I provide the end-of-message decoder myself of course. ] Reading https://gnutls.org/manual/gnutls.html#Asynchronous-operation I'm a bit lost however... it seems kind of clear, but not entirely ;). Is there client example code available somewhere that shows how this can be done? Many thanks for your time, Carlo Wood PS In case anyone is interested; my library in question exists of many git submodules, each of which alone hardly ever make a whole; the only currently existing repository that brings it all together is https://github.com/CarloWood/ai-statefultask-testsuite and the submodule that I'd add the TLS to will be https://github.com/CarloWood/evio PS2 About the end-of-message detection: I don't want to ever copy data around in memory unless absolutely necessary: data is read from a socket into a buffer that is considerably larger than the average message size; whenever all data in the buffer is processed, it starts again at the beginning of the buffer. Only in the event that data comes in faster than it can be processed it might happen that a message wraps over the end into a newly allocated block. In that case (which should seldom happen) I prefer to make a copy into a new buffer to make the message contiguous because decoding contiguous messages is usually much faster and normally they are contiguous anyway. In order to know if a (new) message wraps over the end of the current buffer I simply look if 1) the current memory block is full, 2) there is no 'end-of-message' between where we are and the end of the current block. This can of course be done much much faster than decoding the message, especially for binary protocols that simply have the length of a message in the header of each message (or have fixed size messages, etc). -- Carlo Wood <[email protected]> _______________________________________________ Gnutls-help mailing list [email protected] http://lists.gnupg.org/mailman/listinfo/gnutls-help
