What is wrong with the approach from OpenSSL, Postgres and probably more libraries:
For non-blocking I/O you basically do this:
ssize_t ret = myproto_recv(s, buf, BUFLEN));
if (ret >= 0) {
/* yay! everything went well.
now do something with the
first ret bytes of buf,
0 means connection closed.
*/
return;
}
switch (ret) {
case MYPROTO_WANT_READ:
wait_for(myproto_getfd(s), POLLIN);
break;
case MYPROTO_WANT_WRITE:
wait_for(myproto_getfd(s), POLLOUT);
break;
default:
/* ohh noes! a protocol error occured */
break;
}
Once you detect POLLIN or POLLOUT you just run the code above again. This isn't much different from using raw sockets in non-blocking mode.
Also this should be doable in userspace. If your myproto implementation uses threads in the background, you just return a pipe or an eventfd filedescriptor that you control the other end of.
For blocking I/O it should be even simpler since myproto_recv() will only return
something positive or a protocol error.