[Help-gnutls] timeout?

Oliver Lupton oliverlupton at gmail.com
Mon Jun 5 23:29:15 CEST 2006


mogorman wrote:
> Oliver Lupton wrote:
> 
>> mogorman wrote:
>>
>>> Hello
>>> Can someone provide or explain to me how to use gnutls_recv with a 
>>> timeout, or someway to acheive the same function?
>>>
>>> Thanks
>>> Mog
>>>
>>>
>>> _______________________________________________
>>> Help-gnutls mailing list
>>> Help-gnutls at gnu.org
>>> http://lists.gnu.org/mailman/listinfo/help-gnutls
>>>
>>
>> I'm a little in a rush so sorry there's no examples.
>> There may be a easier way of doing this that's "good enough", but you 
>> can set the socket descriptors non-blocking which will cause 
>> gnutls_record_recv to always return immediately. You can then either 
>> go all the way and make your whole program use async sockets (a pain, 
>> if you've already written a lot), or you can write a wrapper for 
>> gnutls_record_recv to select() for the socket being readable, select() 
>> can timeout :)
>> I can do some examples soon if you need them, just ask :)
>>
>> Cheers,
>> -ol
> 
> yes I would greatly appreciate it if you dont mind, im actually using a 
> jabber library (iksemel) that uses gnutls and it is calling gnutls_recv 
> and never timing out so i am going to have to change it there, but 
> needless to say i have not used gnutls that much.
> 
> Mog
> 

Okay, firstly setting a socket nonblocking:

int flags = fcntl(fd, F_GETFL, 0);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);

Once a socket is nonblocking, no calls to read(), write(), recv(), 
send() etc will ever block, they'll always return immediately.
I'm assuming all the stuff giving gnutls the descriptor and so on is 
working already.

Now, the second way with a wrapper would be something like:

int my_read(gnutls_session_t session, char* buffer, int length, int timeout)
{
	int fd;
	fd_set rfds;
	struct timeval tv;

	fd = (int)gnutls_transport_get_ptr(session);
	tv.tv_sec = length;
	tv.tv_usec = 0;

	FD_ZERO(&rfds);
	FD_SET(fd, &rfds);
	
	int sr = select(fd+1, &rfds, NULL, NULL, &tv);
	
	if(sr == -1)
	{
		/* Shouldn't happen, select() error */
		return -1;
	}
	else if(sr)
	{
		int r = gnutls_record_recv(session, buffer, length);
		
		/* Handle this as you would normally, probably just return it and let 
the caller handle it. */
		return r;
	}
	else
	{
		/* Timeout, however you want to indicate it */
	}
}

Having said that this would be an easy way, I think it may have some 
issues with the handshaking, a possible solution might be to not set the 
socket nonblocking until after the handshake is complete. But maybe 
someone else would have a neater solution?
As for the fully-async way, I don't think I can really show it in one 
example. If you have some understanding of how asynchronous socket apps 
work then it shouldn't be too hard :)

Hope some of this helps

Cheers,
-ol





More information about the Gnutls-help mailing list