Well, I have found the answer to the reliability problem! The flaw is in this code in pkt_buffer.c: static int do_write_str(struct abstract_write *c, struct ol_string *string) { CAST(pkt_buffer, self, c); debug("do_write_str\n"); if (self->super.closed) { ol_string_free(string); return ST_FAIL | ST_CLOSE; } if (self->queue_size == self->queue_max) { /* fifo full */ ol_string_free(string); return ST_FAIL | ST_OK; } So you can see that when the queue is full, the messages simply get dropped. That's bad! The solution is to flush the queue when it is full, and then continue looping over the available input. The question is, what code should be responsible for doing this flushing? Shouldn't some piece of code be checking for the ST_FAIL return code? Cheers, Jeffrey