[gnutls-devel] Question about gnutls_record_uncork

Jaak Ristioja jaak.ristioja at cyber.ee
Mon Dec 9 14:24:31 CET 2013

On 09.12.2013 14:46, Nikos Mavrogiannopoulos wrote:
> On Mon, Dec 9, 2013 at 1:27 PM, Jaak Ristioja <jaak.ristioja at cyber.ee> wrote:
>> Hi!
>> Looking at the source code of the gnutls_record_uncork function in
>> lib/gnutls_record.c it appears that the following might happen:
>>  ...
>>   ret = gnutls_record_send(...); /* ret >= 0 */
>>   ...
>>   total += ret;
>>   ...
>>   ret = gnutls_record_send(...); /* ret < 0 */
>>   ...
>>   return ret;
>> Hence, whatever was stored in the variable "total", is lost even in case
>> of EAGAIN when flags != GNUTLS_RECORD_WAIT. The problem here is that the
>> code calling gnutls_record_uncork has no way to tell how much data was
>> actually sent.
> [...]
>> Are there any other means to check how much pending output data TLS has
>> buffered? Can somebody please comment on this? Thanks!
> You cannot get this information. It is kept internally and will be
> used to send the rest of the data when you call gnutls_record_uncork()
> again. Could you explain about your use-case and why you think you
> need that?

The use case is very complicated, but basically it needs to keep track
of whether all corked data has actually been sent or not. Using
GNUTLS_RECORD_WAIT is not an option for us, because in some cases the
underlying TCP buffers get full on both endpoints at the same time hence
causing a livelock (async. I/O, can't call gnutls_record_recv while the
other thread is in gnutls_record_uncork; both endpoints try to uncork at
the same time).

What might help would be a function to return the value of the variable
session->internals.record_presend_buffer.length. However, I think I will
currently use something like this to work around the problem:

void flush() {
  int ret;
  for (;;) {
      Lock lock(m_sessionLock);
      ret = gnutls_record_uncork(m_session, 0);
    if (ret == 0) break;
    if (ret < 0 && ret != GNUTLS_E_INTERRUPTED && ret != GNUTLS_E_AGAIN)
      throw Exception(...);
    if (needToStop) break;


PS: The documentation states that "On success the number of transmitted
data is returned" by gnutls_record_uncork. Because the non-negative
return value can't be reasonably used, maybe it were be better to state
"On success, a non-negative number is returned".

More information about the Gnutls-devel mailing list