[svn] gpgme - r1362 - in trunk: . assuan src

svn author marcus cvs at cvs.gnupg.org
Wed Apr 8 20:53:58 CEST 2009


Author: marcus
Date: 2009-04-08 20:53:57 +0200 (Wed, 08 Apr 2009)
New Revision: 1362

Modified:
   trunk/TODO
   trunk/assuan/ChangeLog
   trunk/assuan/assuan-buffer.c
   trunk/assuan/assuan-client.c
   trunk/assuan/assuan-handler.c
   trunk/assuan/assuan-inquire.c
   trunk/assuan/assuan-socket.c
   trunk/assuan/assuan.h
   trunk/src/ChangeLog
   trunk/src/engine-assuan.c
   trunk/src/version.c
   trunk/src/w32-glib-io.c
   trunk/src/w32-io.c
   trunk/src/w32-qt-io.cpp
Log:
assuan/
2009-04-08  Marcus Brinkmann  <marcus at g10code.de>

	* assuan.h (_gpgme_io_socket): New prototype.
	(_ASSUAN_CUSTOM_IO, _assuan_custom_close, _assuan_custom_read)
	(_assuan_custom_write, _assuan_custom_pipe, _assuan_custom_socket)
	(_assuan_custom_connect): New macros.
	* assuan-socket.c (_assuan_close, _assuan_sock_new)
	(_assuan_sock_connect) [_ASSUAN_CUSTOM_IO]: Use custom I/O function.
	* assuan-buffer.c (assuan_read_line): Do not handle EAGAIN anymore.
	* assuan-client.c (_assuan_read_from_server): Likewise.
	* assuan-handler.c (process_next): Likewise
	* assuan-inquire.c (assuan_inquire): Likewise.

src/
2009-04-08  Marcus Brinkmann  <marcus at g10code.de>

	* w32-glib-io.c (giochannel_table): New members used, fd, socket.
	(find_channel): Drop CREATE argument.
	(new_dummy_channel_from_fd, new_channel_from_fd)
	(new_channel_from_socket): New functions.
	(_gpgm_io_fd2str): Implement for sockets.
	(_gpgme_io_write, _gpgme_io_read): Translate EAGAIN errors
	correctly.
	(_gpgme_io_pipe): Fix for new channel bookkeeping.
	(_gpgme_io_close, _gpgme_io_dup): Likewise.
	(wsa2errno, _gpgme_io_socket, _gpgme_io_connect): New.
	* w32-io.c (MAX_READERS, MAX_WRITERS): Bump up to 40.
	(wsa2errno, _gpgme_io_socket, _gpgme_io_connect): New.
	* w32-qt-io.cpp (_gpgme_io_socket, _gpgme_io_connect): New stubs.
	* version.c [HAVE_W32_SYSTEM]: Include "windows.h.
	(do_subsystem_inits) [HAVE_W32_SYSTEM]: Call WSAStartup.
	* engine-assuan.c (llass_status_handler): Ignore EAGAIN errors.


Modified: trunk/assuan/ChangeLog
===================================================================
--- trunk/assuan/ChangeLog	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/assuan/ChangeLog	2009-04-08 18:53:57 UTC (rev 1362)
@@ -1,3 +1,16 @@
+2009-04-08  Marcus Brinkmann  <marcus at g10code.de>
+
+	* assuan.h (_gpgme_io_socket): New prototype.
+	(_ASSUAN_CUSTOM_IO, _assuan_custom_close, _assuan_custom_read)
+	(_assuan_custom_write, _assuan_custom_pipe, _assuan_custom_socket)
+	(_assuan_custom_connect): New macros.
+	* assuan-socket.c (_assuan_close, _assuan_sock_new)
+	(_assuan_sock_connect) [_ASSUAN_CUSTOM_IO]: Use custom I/O function.
+	* assuan-buffer.c (assuan_read_line): Do not handle EAGAIN anymore.
+	* assuan-client.c (_assuan_read_from_server): Likewise.
+	* assuan-handler.c (process_next): Likewise
+	* assuan-inquire.c (assuan_inquire): Likewise.
+
 2009-03-23  Marcus Brinkmann  <marcus at g10code.de>
 
 	* assuan.h: Add prefix macros for _assuan_close and _assuan_usleep.

Modified: trunk/src/ChangeLog
===================================================================
--- trunk/src/ChangeLog	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/src/ChangeLog	2009-04-08 18:53:57 UTC (rev 1362)
@@ -1,3 +1,22 @@
+2009-04-08  Marcus Brinkmann  <marcus at g10code.de>
+
+	* w32-glib-io.c (giochannel_table): New members used, fd, socket.
+	(find_channel): Drop CREATE argument.
+	(new_dummy_channel_from_fd, new_channel_from_fd)
+	(new_channel_from_socket): New functions.
+	(_gpgm_io_fd2str): Implement for sockets.
+	(_gpgme_io_write, _gpgme_io_read): Translate EAGAIN errors
+	correctly.
+	(_gpgme_io_pipe): Fix for new channel bookkeeping.
+	(_gpgme_io_close, _gpgme_io_dup): Likewise.
+	(wsa2errno, _gpgme_io_socket, _gpgme_io_connect): New.
+	* w32-io.c (MAX_READERS, MAX_WRITERS): Bump up to 40.
+	(wsa2errno, _gpgme_io_socket, _gpgme_io_connect): New.
+	* w32-qt-io.cpp (_gpgme_io_socket, _gpgme_io_connect): New stubs.
+	* version.c [HAVE_W32_SYSTEM]: Include "windows.h.
+	(do_subsystem_inits) [HAVE_W32_SYSTEM]: Call WSAStartup.
+	* engine-assuan.c (llass_status_handler): Ignore EAGAIN errors.
+
 2009-03-18  Werner Koch  <wk at g10code.com>
 
 	* gpgme.h.in (GPGME_KEYLIST_MODE_EPHEMERAL): New.

Modified: trunk/TODO
===================================================================
--- trunk/TODO	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/TODO	2009-04-08 18:53:57 UTC (rev 1362)
@@ -1,5 +1,12 @@
 Hey Emacs, this is -*- outline -*- mode!
 
+* IMPORTANT
+** When using descriptor passing, we need to set the fd to blocking before
+   issueing simple commands, because we are mixing synchronous
+   commands into potentially asynchronous operations.
+** Might want to implement nonblock for w32 native backend!  Right now,
+   we block reading the next line with assuan.
+
 * Before release:
 ** Figure out if _gpgme_io_pipe should pre-create reader/writer and if we
    then can use !start_it in most invocations.  Note that gpgme_io_dup

Modified: trunk/assuan/assuan-buffer.c
===================================================================
--- trunk/assuan/assuan-buffer.c	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/assuan/assuan-buffer.c	2009-04-08 18:53:57 UTC (rev 1362)
@@ -245,11 +245,7 @@
   if (!ctx)
     return _assuan_error (ASSUAN_Invalid_Value);
 
-  do
-    {
-      err = _assuan_read_line (ctx);
-    }
-  while (_assuan_error_is_eagain (err));
+  err = _assuan_read_line (ctx);
 
   *line = ctx->inbound.line;
   *linelen = ctx->inbound.linelen;

Modified: trunk/assuan/assuan-client.c
===================================================================
--- trunk/assuan/assuan-client.c	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/assuan/assuan-client.c	2009-04-08 18:53:57 UTC (rev 1362)
@@ -42,16 +42,12 @@
   *off = 0;
   do 
     {
-      do
-	{
-	  rc = _assuan_read_line (ctx);
-	}
-      while (_assuan_error_is_eagain (rc));
+      rc = _assuan_read_line (ctx);
       if (rc)
         return rc;
       line = ctx->inbound.line;
       linelen = ctx->inbound.linelen;
-    }    
+    }
   while (*line == '#' || !linelen);
 
   if (linelen >= 1

Modified: trunk/assuan/assuan-handler.c
===================================================================
--- trunk/assuan/assuan-handler.c	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/assuan/assuan-handler.c	2009-04-08 18:53:57 UTC (rev 1362)
@@ -630,8 +630,6 @@
      required to write full lines without blocking long after starting
      a partial line.  */
   rc = _assuan_read_line (ctx);
-  if (_assuan_error_is_eagain (rc))
-    return 0;
   if (rc)
     return rc;
   if (*ctx->inbound.line == '#' || !ctx->inbound.linelen)

Modified: trunk/assuan/assuan-inquire.c
===================================================================
--- trunk/assuan/assuan-inquire.c	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/assuan/assuan-inquire.c	2009-04-08 18:53:57 UTC (rev 1362)
@@ -169,9 +169,7 @@
     {
       do 
         {
-	  do
-	    rc = _assuan_read_line (ctx);
-	  while (_assuan_error_is_eagain (rc));
+	  rc = _assuan_read_line (ctx);
           if (rc)
             goto leave;
           line = (unsigned char *) ctx->inbound.line;

Modified: trunk/assuan/assuan-socket.c
===================================================================
--- trunk/assuan/assuan-socket.c	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/assuan/assuan-socket.c	2009-04-08 18:53:57 UTC (rev 1362)
@@ -145,7 +145,10 @@
 int
 _assuan_close (assuan_fd_t fd)
 {
-#if defined (HAVE_W32_SYSTEM) && !defined(_ASSUAN_IN_GPGME_BUILD_ASSUAN)
+#ifdef _ASSUAN_CUSTOM_IO
+  return _assuan_custom_close (fd);
+#else
+#ifdef (HAVE_W32_SYSTEM)
   int rc = closesocket (HANDLE2SOCKET(fd));
   if (rc)
     errno = _assuan_sock_wsa2errno (WSAGetLastError ());
@@ -160,6 +163,7 @@
 #else
   return close (fd);
 #endif
+#endif
 }
 
 
@@ -173,13 +177,25 @@
   assuan_fd_t res;
   if (domain == AF_UNIX || domain == AF_LOCAL)
     domain = AF_INET;
+
+#ifdef _ASSUAN_CUSTOM_IO
+  return _assuan_custom_socket (domain, type, proto);
+#else
   res = SOCKET2HANDLE(socket (domain, type, proto));
   if (res == ASSUAN_INVALID_FD)
     errno = _assuan_sock_wsa2errno (WSAGetLastError ());
   return res;
+#endif
+
 #else
+
+#ifdef _ASSUAN_CUSTOM_IO
+  return _gpgme_io_socket (domain, type, proto);
+#else
   return socket (domain, type, proto);
 #endif
+
+#endif
 }
 
 
@@ -208,11 +224,18 @@
       unaddr->sun_port = myaddr.sin_port;
       unaddr->sun_addr.s_addr = myaddr.sin_addr.s_addr;
   
+#ifdef _ASSUAN_CUSTOM_IO
+      ret = _assuan_custom_connect (sockfd,
+				    (struct sockaddr *)&myaddr, sizeof myaddr);
+#else
       ret = connect (HANDLE2SOCKET(sockfd), 
                      (struct sockaddr *)&myaddr, sizeof myaddr);
+#endif
+
       if (!ret)
         {
           /* Send the nonce. */
+
           ret = _assuan_io_write (sockfd, nonce, 16);
           if (ret >= 0 && ret != 16)
             {
@@ -220,6 +243,8 @@
               ret = -1;
             }
         }
+      else
+        errno = _assuan_sock_wsa2errno (WSAGetLastError ());
       return ret;
     }
   else
@@ -231,8 +256,14 @@
       return res;
     }      
 #else
+
+#ifdef _ASSUAN_CUSTOM_IO
+  return _assuan_custom_connect (sockfd, addr, addrlen);
+#else
   return connect (sockfd, addr, addrlen);
 #endif
+
+#endif
 }
 
 

Modified: trunk/assuan/assuan.h
===================================================================
--- trunk/assuan/assuan.h	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/assuan/assuan.h	2009-04-08 18:53:57 UTC (rev 1362)
@@ -77,6 +77,7 @@
 int _gpgme_io_write (int fd, const void *buffer, size_t count);
 int _gpgme_io_sendmsg (int sock, const struct msghdr *msg, int flags);
 int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);
+int _gpgme_io_socket (int domain, int type, int proto);
 
 #define _assuan_funopen _gpgme_funopen
 
@@ -90,6 +91,15 @@
 #define sendmsg	      _gpgme_io_sendmsg
 #define recvmsg       _gpgme_io_recvmsg
 #endif /*_ASSUAN_IN_GPGME_BUILD_ASSUAN*/
+
+#define _ASSUAN_CUSTOM_IO 1
+#define _assuan_custom_close _gpgme_io_close
+#define _assuan_custom_read _gpgme_io_read
+#define _assuan_custom_write _gpgme_io_write
+#define _assuan_custom_pipe _gpgme_io_pipe
+#define _assuan_custom_socket _gpgme_io_socket
+#define _assuan_custom_connect _gpgme_io_connect
+
 /**** End GPGME specific modifications. ******/
 
 

Modified: trunk/src/engine-assuan.c
===================================================================
--- trunk/src/engine-assuan.c	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/src/engine-assuan.c	2009-04-08 18:53:57 UTC (rev 1362)
@@ -415,7 +415,18 @@
       err = assuan_read_line (llass->assuan_ctx, &line, &linelen);
       if (err)
 	{
-          TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
+	  /* Reading a full line may not be possible when
+	     communicating over a socket in nonblocking mode.  In this
+	     case, we are done for now.  */
+	  if (gpg_err_code (err) == GPG_ERR_EAGAIN)
+	    {
+	      TRACE1 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
+		      "fd 0x%x: EAGAIN reading assuan line (ignored)", fd);
+	      err = 0;
+	      continue;
+	    }
+	  
+	  TRACE2 (DEBUG_CTX, "gpgme:llass_status_handler", llass,
 		  "fd 0x%x: error reading assuan line: %s",
                   fd, gpg_strerror (err));
 	}

Modified: trunk/src/version.c
===================================================================
--- trunk/src/version.c	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/src/version.c	2009-04-08 18:53:57 UTC (rev 1362)
@@ -40,6 +40,10 @@
 #include "assuan.h"
 #endif
 
+#ifdef HAVE_W32_SYSTEM
+#include "windows.h"
+#endif
+
 
 /* Bootstrap the subsystems needed for concurrent operation.  This
    must be done once at startup.  We can not guarantee this using a
@@ -54,6 +58,14 @@
   if (done)
     return;
 
+#ifdef HAVE_W32_SYSTEM
+      {
+        WSADATA wsadat;
+        
+        WSAStartup (0x202, &wsadat);
+      }
+#endif
+
   _gpgme_sema_subsystem_init ();
 #ifdef HAVE_ASSUAN_H
   assuan_set_assuan_err_source (GPG_ERR_SOURCE_GPGME);

Modified: trunk/src/w32-glib-io.c
===================================================================
--- trunk/src/w32-glib-io.c	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/src/w32-glib-io.c	2009-04-08 18:53:57 UTC (rev 1362)
@@ -80,6 +80,13 @@
 
 static struct 
 {
+  int used;
+
+  /* If this is not -1, then it's a libc file descriptor.  */
+  int fd;
+  /* If fd is -1, this is the Windows socket handle.  */
+  int socket;
+
   GIOChannel *chan;
   /* The boolean PRIMARY is true if this file descriptor caused the
      allocation of CHAN.  Only then should CHAN be destroyed when this
@@ -102,28 +109,104 @@
 
 
 static GIOChannel *
-find_channel (int fd, int create)
+find_channel (int fd)
 {
   if (fd < 0 || fd >= MAX_SLAFD)
     return NULL;
 
-  if (create && !giochannel_table[fd].chan)
+  return giochannel_table[fd].chan;
+}
+
+
+/* Returns the FD or -1 on resource limit.  */
+int
+new_dummy_channel_from_fd (int cfd)
+{
+  int idx;
+
+  for (idx = 0; idx < MAX_SLAFD; idx++)
+    if (! giochannel_table[idx].used)
+      break;
+
+  if (idx == MAX_SLAFD)
     {
-      giochannel_table[fd].chan = g_io_channel_win32_new_fd (fd);
-      giochannel_table[fd].primary = 1;
-      g_io_channel_set_encoding (giochannel_table[fd].chan, NULL, NULL);
-      g_io_channel_set_buffered (giochannel_table[fd].chan, FALSE);
+      errno = EIO;
+      return -1;
     }
 
-  return giochannel_table[fd].chan;
+  giochannel_table[idx].used = 1;
+  giochannel_table[idx].chan = NULL;
+  giochannel_table[idx].fd = cfd;
+  giochannel_table[idx].socket = INVALID_SOCKET;
+  giochannel_table[idx].primary = 1;
+
+  return idx;
 }
 
 
+/* Returns the FD or -1 on resource limit.  */
+int
+new_channel_from_fd (int cfd)
+{
+  int idx;
+
+  for (idx = 0; idx < MAX_SLAFD; idx++)
+    if (! giochannel_table[idx].used)
+      break;
+
+  if (idx == MAX_SLAFD)
+    {
+      errno = EIO;
+      return -1;
+    }
+
+  giochannel_table[idx].used = 1;
+  giochannel_table[idx].chan = g_io_channel_win32_new_fd (cfd);
+  giochannel_table[idx].fd = cfd;
+  giochannel_table[idx].socket = INVALID_SOCKET;
+  giochannel_table[idx].primary = 1;
+
+  g_io_channel_set_encoding (giochannel_table[idx].chan, NULL, NULL);
+  g_io_channel_set_buffered (giochannel_table[idx].chan, FALSE);
+
+  return idx;
+}
+
+
+/* Returns the FD or -1 on resource limit.  */
+int
+new_channel_from_socket (int sock)
+{
+  int idx;
+
+  for (idx = 0; idx < MAX_SLAFD; idx++)
+    if (! giochannel_table[idx].used)
+      break;
+
+  if (idx == MAX_SLAFD)
+    {
+      errno = EIO;
+      return -1;
+    }
+
+  giochannel_table[idx].used = 1;
+  giochannel_table[idx].chan = g_io_channel_win32_new_socket (sock);
+  giochannel_table[idx].fd = -1;
+  giochannel_table[idx].socket = sock;
+  giochannel_table[idx].primary = 1;
+
+  g_io_channel_set_encoding (giochannel_table[idx].chan, NULL, NULL);
+  g_io_channel_set_buffered (giochannel_table[idx].chan, FALSE);
+
+  return idx;
+}
+
+
 /* Compatibility interface.  Obsolete.  */
 void *
 gpgme_get_giochannel (int fd)
 {
-  return find_channel (fd, 0);
+  return find_channel (fd);
 }
 
 
@@ -131,7 +214,7 @@
 void *
 gpgme_get_fdptr (int fd)
 {
-  return find_channel (fd, 0);
+  return find_channel (fd);
 }
 
 
@@ -141,9 +224,17 @@
 int
 _gpgme_io_fd2str (char *buf, int buflen, int fd)
 {
+  HANDLE hndl;
+    
   TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_fd2str", fd, "fd=%d", fd);
-  TRACE_SUC1 ("syshd=%p", _get_osfhandle (fd));
-  return snprintf (buf, buflen, "%d", (int) _get_osfhandle (fd));
+  if (giochannel_table[fd].fd != -1)
+    hndl = (HANDLE) _get_osfhandle (giochannel_table[fd].fd);
+  else
+    hndl = (HANDLE) giochannel_table[fd].socket;
+
+  TRACE_SUC1 ("syshd=%p", hndl);
+  
+  return snprintf (buf, buflen, "%d", (int) hndl);
 }
 
 
@@ -170,7 +261,7 @@
   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd,
 	      "buffer=%p, count=%u", buffer, count);
 
-  chan = find_channel (fd, 0);
+  chan = find_channel (fd);
   if (!chan)
     {
       TRACE_LOG ("no channel registered");
@@ -192,15 +283,21 @@
 
   if (status == G_IO_STATUS_EOF)
     nread = 0;
+  else if (status == G_IO_STATUS_AGAIN)
+    {
+      nread = -1;
+      saved_errno = EAGAIN;
+    }
   else if (status != G_IO_STATUS_NORMAL)
     {
       TRACE_LOG1 ("status %d", status);
       nread = -1;
       saved_errno = EIO;
     }
+  
+  if (nread != 0 && nread != -1)
+    TRACE_LOGBUF (buffer, nread);
 
-  TRACE_LOGBUF (buffer, nread);
-
   errno = saved_errno;
   return TRACE_SYSRES (nread);
 }
@@ -213,11 +310,13 @@
   gsize nwritten;
   GIOChannel *chan;
   GIOStatus status;
+  GError *err = NULL;
+
   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd,
 	      "buffer=%p, count=%u", buffer, count);
   TRACE_LOGBUF (buffer, count);
 
-  chan = find_channel (fd, 0);
+  chan = find_channel (fd);
   if (!chan)
     {
       TRACE_LOG ("fd %d: no channel registered");
@@ -226,10 +325,21 @@
     }
 
   status = g_io_channel_write_chars (chan, (gchar *) buffer, count,
-				     &nwritten, NULL);
-  if (status != G_IO_STATUS_NORMAL)
+				     &nwritten, &err);
+  if (err)
     {
+      TRACE_LOG1 ("write error: %s", err->message);
+      g_error_free (err);
+    }
+
+  if (status == G_IO_STATUS_AGAIN)
+    {
       nwritten = -1;
+      saved_errno = EAGAIN;
+    }
+  else if (status != G_IO_STATUS_NORMAL)
+    {
+      nwritten = -1;
       saved_errno = EIO;
     }
   errno = saved_errno;
@@ -241,13 +351,14 @@
 int
 _gpgme_io_pipe (int filedes[2], int inherit_idx)
 {
-  GIOChannel *chan;
+  int fds[2];
+
   TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
 	      "inherit_idx=%i (GPGME uses it for %s)",
 	      inherit_idx, inherit_idx ? "reading" : "writing");
 
 #define PIPEBUF_SIZE  4096
-  if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
+  if (_pipe (fds, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
     return TRACE_SYSRES (-1);
 
   /* Make one end inheritable. */
@@ -255,13 +366,13 @@
     {
       int new_read;
 
-      new_read = _dup (filedes[0]);
-      _close (filedes[0]);
-      filedes[0] = new_read;
+      new_read = _dup (fds[0]);
+      _close (fds[0]);
+      fds[0] = new_read;
 
       if (new_read < 0)
 	{
-	  _close (filedes[1]);
+	  _close (fds[1]);
 	  return TRACE_SYSRES (-1);
 	}
     }
@@ -269,33 +380,48 @@
     {
       int new_write;
 
-      new_write = _dup (filedes[1]);
-      _close (filedes[1]);
-      filedes[1] = new_write;
+      new_write = _dup (fds[1]);
+      _close (fds[1]);
+      fds[1] = new_write;
 
       if (new_write < 0)
 	{
-	  _close (filedes[0]);
+	  _close (fds[0]);
 	  return TRACE_SYSRES (-1);
 	}
     }
 
-  /* Now we have a pipe with the right end inheritable.  The other end
+  /* For _gpgme_io_close.  */
+  filedes[inherit_idx] = new_dummy_channel_from_fd (fds[inherit_idx]);
+  if (filedes[inherit_idx] < 0)
+    {
+      int saved_errno = errno;
+      
+      _close (fds[0]);
+      _close (fds[1]);
+      errno = saved_errno;
+      return TRACE_SYSRES (-1);
+    }
+
+  /* Now we have a pipe with the correct end inheritable.  The other end
      should have a giochannel.  */
-  chan = find_channel (filedes[1 - inherit_idx], 1);
-  if (!chan)
+  filedes[1 - inherit_idx] = new_channel_from_fd (fds[1 - inherit_idx]);
+  if (filedes[1 - inherit_idx] < 0)
     {
       int saved_errno = errno;
-      _close (filedes[0]);
-      _close (filedes[1]);
+      
+      _gpgme_io_close (fds[inherit_idx]);
+      _close (fds[1 - inherit_idx]);
       errno = saved_errno;
       return TRACE_SYSRES (-1);
     }
-
+  
   return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p",
-	  filedes[0], (HANDLE) _get_osfhandle (filedes[0]),
-	  filedes[1], (HANDLE) _get_osfhandle (filedes[1]),
-	  chan);
+		     filedes[0],
+		     (HANDLE) _get_osfhandle (giochannel_table[filedes[0]].fd),
+		     filedes[1],
+		     (HANDLE) _get_osfhandle (giochannel_table[filedes[1]].fd),
+		     giochannel_table[1 - inherit_idx].chan);
 }
 
 
@@ -310,6 +436,8 @@
       return TRACE_SYSRES (-1);
     }
 
+  assert (giochannel_table[fd].used);
+
   /* First call the notify handler.  */
   if (notify_table[fd].handler)
     {
@@ -318,19 +446,26 @@
       notify_table[fd].value = NULL;
     }
 
-  /* Then do the close.  */    
+  /* Then do the close.  */
   if (giochannel_table[fd].chan)
     {
       if (giochannel_table[fd].primary)
 	g_io_channel_shutdown (giochannel_table[fd].chan, 1, NULL);
-      else
-	_close (fd);
-
+      
       g_io_channel_unref (giochannel_table[fd].chan);
-      giochannel_table[fd].chan = NULL;
     }
   else
-    _close (fd);
+    {
+      /* Dummy entry, just close.  */
+      assert (giochannel_table[fd].fd != -1);
+      _close (giochannel_table[fd].fd);
+    }
+	
+  giochannel_table[fd].used = 0;
+  giochannel_table[fd].fd = -1;
+  giochannel_table[fd].socket = INVALID_SOCKET;
+  giochannel_table[fd].chan = NULL;
+  giochannel_table[fd].primary = 0;
 
   TRACE_SUC ();
   return 0;
@@ -365,16 +500,17 @@
  
   TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd);
 
-  chan = find_channel (fd, 0);
+  chan = find_channel (fd);
   if (!chan)
     {
       errno = EIO;
       return TRACE_SYSRES (-1);
     }
 
-   status = g_io_channel_set_flags (chan,
+  status = g_io_channel_set_flags (chan,
 				   g_io_channel_get_flags (chan) |
 				   G_IO_FLAG_NONBLOCK, NULL);
+
   if (status != G_IO_STATUS_NORMAL)
     {
 #if 0
@@ -549,7 +685,8 @@
       HANDLE hd;
 
       /* Make it inheritable for the wrapper process.  */
-      if (!DuplicateHandle (GetCurrentProcess(), _get_osfhandle (fd_list[i].fd),
+      if (!DuplicateHandle (GetCurrentProcess(),
+			    _get_osfhandle (giochannel_table[fd_list[i].fd].fd),
 			    pi.hProcess, &hd, 0, TRUE, DUPLICATE_SAME_ACCESS))
 	{
 	  TRACE_LOG1 ("DuplicateHandle failed: ec=%d", (int) GetLastError ());
@@ -694,7 +831,7 @@
 	continue;
 
       if ((fds[i].for_read || fds[i].for_write)
-          && !(chan = find_channel (fds[i].fd, 0)))
+          && !(chan = find_channel (fds[i].fd)))
         {
           TRACE_ADD1 (dbg_help, "[BAD0x%x ", fds[i].fd);
           TRACE_END (dbg_help, "]"); 
@@ -786,27 +923,147 @@
 {
   int newfd;
   GIOChannel *chan;
-  
-  TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_dup", fd, "dup (%d)", fd);
 
-  newfd = _dup (fd);
-  if (newfd == -1)
-    return TRACE_SYSRES (-1);
-  if (newfd < 0 || newfd >= MAX_SLAFD)
+  TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd);
+
+  if (fd < 0 || fd >= MAX_SLAFD || !giochannel_table[fd].used)
     {
-      /* New FD won't fit into our table.  */
-      _close (newfd);
-      errno = EIO; 
+      errno = EINVAL;
       return TRACE_SYSRES (-1);
     }
-  assert (giochannel_table[newfd].chan == NULL);
 
-  chan = find_channel (fd, 0);
-  assert (chan);
-
+  for (newfd = 0; newfd < MAX_SLAFD; newfd++)
+    if (! giochannel_table[newfd].used)
+      break;
+  if (newfd == MAX_SLAFD)
+    {
+      errno = EIO;
+      return TRACE_SYSRES (-1);
+    }
+  
+  chan = giochannel_table[fd].chan;
   g_io_channel_ref (chan);
+  giochannel_table[newfd].used = 1;
   giochannel_table[newfd].chan = chan;
+  giochannel_table[newfd].fd = -1;
+  giochannel_table[newfd].socket = INVALID_SOCKET;
   giochannel_table[newfd].primary = 0;
 
   return TRACE_SYSRES (newfd);
 }
+
+
+
+
+
+static int
+wsa2errno (int err)
+{
+  switch (err)
+    {
+    case WSAENOTSOCK:
+      return EINVAL;
+    case WSAEWOULDBLOCK:
+      return EAGAIN;
+    case ERROR_BROKEN_PIPE:
+      return EPIPE;
+    case WSANOTINITIALISED:
+      return ENOSYS;
+    default:
+      return EIO;
+    }
+}
+
+
+int
+_gpgme_io_socket (int domain, int type, int proto)
+{
+  int res;
+  int fd;
+
+  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain,
+	      "type=%i, protp=%i", type, proto);
+
+  res = socket (domain, type, proto);
+  if (res == INVALID_SOCKET)
+    {
+      errno = wsa2errno (WSAGetLastError ());
+      return TRACE_SYSRES (-1);
+    }
+
+  fd = new_channel_from_socket (res);
+  if (fd < 0)
+    {
+      int saved_errno = errno;
+      closesocket (res);
+      errno = saved_errno;
+      return TRACE_SYSRES (-1);
+    }
+
+  TRACE_SUC2 ("fd=%i, socket=0x%x", fd, res);
+  
+  return fd;
+}
+
+
+int
+_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
+{
+  GIOChannel *chan; 
+  int sockfd;
+  int res;
+  GIOFlags flags;
+  GIOStatus status;
+  GError *err = NULL;
+
+  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
+	      "addr=%p, addrlen=%i", addr, addrlen);
+
+  chan = find_channel (fd);
+  if (! chan)
+    {
+      errno = EINVAL;
+      return TRACE_SYSRES (-1);
+    }
+
+  flags = g_io_channel_get_flags (chan);
+  if (flags & G_IO_FLAG_NONBLOCK)
+    {
+      status = g_io_channel_set_flags (chan, flags & ~G_IO_FLAG_NONBLOCK, &err);
+      if (err)
+	{
+	  TRACE_LOG1 ("setting flags error: %s", err->message);
+	  g_error_free (err);
+	  err = NULL;
+	}
+      if (status != G_IO_STATUS_NORMAL)
+	{
+	  errno = EIO;
+	  return TRACE_SYSRES (-1);
+	}
+    }
+
+  sockfd = giochannel_table[fd].socket;
+  if (sockfd == INVALID_SOCKET)
+    {
+      errno = EINVAL;
+      return TRACE_SYSRES (-1);
+    }
+
+  TRACE_LOG1 ("connect sockfd=0x%x", sockfd);
+  res = connect (sockfd, addr, addrlen);
+
+  /* FIXME: Error ignored here.  */
+  if (! (flags & G_IO_FLAG_NONBLOCK))
+    g_io_channel_set_flags (chan, flags, NULL);
+
+  if (res)
+    {
+      TRACE_LOG2 ("connect failed: %i %i", res, WSAGetLastError ());
+
+      errno = wsa2errno (WSAGetLastError ());
+      return TRACE_SYSRES (-1);
+    }
+
+  return TRACE_SUC ();
+}

Modified: trunk/src/w32-io.c
===================================================================
--- trunk/src/w32-io.c	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/src/w32-io.c	2009-04-08 18:53:57 UTC (rev 1362)
@@ -53,8 +53,8 @@
 #define READBUF_SIZE 4096
 #define WRITEBUF_SIZE 4096
 #define PIPEBUF_SIZE  4096
-#define MAX_READERS 20
-#define MAX_WRITERS 20
+#define MAX_READERS 40
+#define MAX_WRITERS 40
 
 static struct
 {
@@ -1469,3 +1469,63 @@
 {
   return NULL;
 }
+
+
+static int
+wsa2errno (int err)
+{
+  switch (err)
+    {
+    case WSAENOTSOCK:
+      return EINVAL;
+    case WSAEWOULDBLOCK:
+      return EAGAIN;
+    case ERROR_BROKEN_PIPE:
+      return EPIPE;
+    case WSANOTINITIALISED:
+      return ENOSYS;
+    default:
+      return EIO;
+    }
+}
+
+
+int
+_gpgme_io_socket (int domain, int type, int proto)
+{
+  int res;
+
+  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain,
+	      "type=%i, protp=%i", type, proto);
+
+  res = socket (domain, type, proto);
+  if (res == INVALID_SOCKET)
+    {
+      errno = wsa2errno (WSAGetLastError ());
+      return TRACE_SYSRES (-1);
+    }
+
+  TRACE_SUC1 ("socket=0x%x", res);
+  
+  return res;
+}
+
+
+int
+_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
+{
+  int sockfd;
+  int res;
+
+  TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
+	      "addr=%p, addrlen=%i", addr, addrlen);
+
+  res = connect (sockfd, addr, addrlen);
+  if (!res)
+    {
+      errno = wsa2errno (WSAGetLastError ());
+      return TRACE_SYSRES (-1);
+    }
+
+  return TRACE_SUC ();
+}

Modified: trunk/src/w32-qt-io.cpp
===================================================================
--- trunk/src/w32-qt-io.cpp	2009-03-23 22:23:25 UTC (rev 1361)
+++ trunk/src/w32-qt-io.cpp	2009-04-08 18:53:57 UTC (rev 1362)
@@ -674,3 +674,20 @@
     return fd;
 }
 
+
+extern "C"
+int
+_gpgme_io_socket (int domain, int type, int proto)
+{
+  errno = EIO;
+  return -1;
+}
+
+
+extern "C"
+int
+_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
+{
+  errno = EIO;
+  return -1;
+}




More information about the Gnupg-commits mailing list