[gnutls-dev] Re: GnuTLS for Windows

Simon Josefsson jas at extundo.com
Sat Jul 29 12:33:51 CEST 2006


Werner Koch <wk at gnupg.org> writes:

> On Sun, 16 Jul 2006 15:18, Simon Josefsson said:
>
>> Alas, Windows' select() only works on sockets, not file descriptors.
>> gnutls-cli uses select to find out whether there is data on stdin and
>> from the server, and it is the stdin part that doesn't work.  I think
>> there are some solutions to this, but it's not clear to me how to
>> implement them yet.
>
> Checkout gpgme: gpgme/w32-io.c shows how to do it. There is also a
> posix-io.c of course.  The latest glib has similar code now as well as
> special cases for sockets.  It is all a mess: WaitForMultipleObjects
> is not able to wait on all types of file descriptors. In particular if
> you are working with CreatePipe, you need to have a thread for each fd
> you want to wait on.

Yes, it looks slightly messy.  GDB has some code for it too
(mingw-hdep.c).

It may be possible to use a simpler select() replacement in cli.c,
because it only waits for stdin and one network stream.  For
reference, I'm currently experimenting with something like the
below...  Obviously not perfect, but it is a test tool after all.

Eventually, I think we should have a gnulib module with a proper w32
select call.

/Simon

int
w32_select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
	    struct timeval *timeout)
{
  int fd;

  for (fd = 0; fd < n; fd++)
    {
      if (readfds && FD_ISSET (fd, readfds))
	{
	  HANDLE h;
	  DWORD available;
	  h = (HANDLE) _get_osfhandle (fd);
	  if (h != -1 && PeekNamedPipe (h, NULL, 0, NULL, &available, NULL))
	    {
	      if (available == 0)
		FD_CLR (fd, readfds);
	    }
	  else
	    {
	      int err;
	      struct timeval tv;
	      fd_set new;
	      WSANETWORKEVENTS events;

	      err = WSAEnumNetworkEvents(fd, NULL, &events);
	      if (events.lNetworkEvents)
		printf ("ff %d\n", events.lNetworkEvents);

	      FD_ZERO (&new);
	      FD_SET (fd, &new);
	      tv.tv_sec = 0;
	      tv.tv_usec = 100;

	      err = select (fd + 1, &new, NULL, NULL, &tv);
	      if (err == 0)
		  FD_CLR (fd, readfds);
	      else if (err < 0)
		printf ("bad\n");
	    }
	}
    }
  return 0;
}




More information about the Gnutls-devel mailing list