diff options
| author | Marcus Brinkmann <[email protected]> | 2009-04-08 18:53:57 +0000 | 
|---|---|---|
| committer | Marcus Brinkmann <[email protected]> | 2009-04-08 18:53:57 +0000 | 
| commit | d255b4bec9a1fdf0864640750161ea12999e43a5 (patch) | |
| tree | 75e870ff7e07cb4f2bf30dc8a136c72eb4bf6bd4 | |
| parent | 2009-03-23 Marcus Brinkmann <[email protected]> (diff) | |
| download | gpgme-d255b4bec9a1fdf0864640750161ea12999e43a5.tar.gz gpgme-d255b4bec9a1fdf0864640750161ea12999e43a5.zip | |
assuan/
2009-04-08  Marcus Brinkmann  <[email protected]>
	* 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  <[email protected]>
	* 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.
| -rw-r--r-- | TODO | 7 | ||||
| -rw-r--r-- | assuan/ChangeLog | 13 | ||||
| -rw-r--r-- | assuan/assuan-buffer.c | 6 | ||||
| -rw-r--r-- | assuan/assuan-client.c | 8 | ||||
| -rw-r--r-- | assuan/assuan-handler.c | 2 | ||||
| -rw-r--r-- | assuan/assuan-inquire.c | 4 | ||||
| -rw-r--r-- | assuan/assuan-socket.c | 33 | ||||
| -rw-r--r-- | assuan/assuan.h | 10 | ||||
| -rw-r--r-- | src/ChangeLog | 19 | ||||
| -rw-r--r-- | src/engine-assuan.c | 13 | ||||
| -rw-r--r-- | src/version.c | 12 | ||||
| -rw-r--r-- | src/w32-glib-io.c | 375 | ||||
| -rw-r--r-- | src/w32-io.c | 64 | ||||
| -rw-r--r-- | src/w32-qt-io.cpp | 17 | 
14 files changed, 504 insertions, 79 deletions
| @@ -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 diff --git a/assuan/ChangeLog b/assuan/ChangeLog index 18e14ed8..8dd2ebbd 100644 --- a/assuan/ChangeLog +++ b/assuan/ChangeLog @@ -1,3 +1,16 @@ +2009-04-08  Marcus Brinkmann  <[email protected]> + +	* 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  <[email protected]>  	* assuan.h: Add prefix macros for _assuan_close and _assuan_usleep. diff --git a/assuan/assuan-buffer.c b/assuan/assuan-buffer.c index b9e35721..e825d9ff 100644 --- a/assuan/assuan-buffer.c +++ b/assuan/assuan-buffer.c @@ -245,11 +245,7 @@ assuan_read_line (assuan_context_t ctx, char **line, size_t *linelen)    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; diff --git a/assuan/assuan-client.c b/assuan/assuan-client.c index 15f4f1cd..e123e764 100644 --- a/assuan/assuan-client.c +++ b/assuan/assuan-client.c @@ -42,16 +42,12 @@ _assuan_read_from_server (assuan_context_t ctx, int *okay, int *off)    *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 diff --git a/assuan/assuan-handler.c b/assuan/assuan-handler.c index b940bfd4..f504abef 100644 --- a/assuan/assuan-handler.c +++ b/assuan/assuan-handler.c @@ -630,8 +630,6 @@ process_next (assuan_context_t ctx)       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) diff --git a/assuan/assuan-inquire.c b/assuan/assuan-inquire.c index 58b9f029..ab710a12 100644 --- a/assuan/assuan-inquire.c +++ b/assuan/assuan-inquire.c @@ -169,9 +169,7 @@ assuan_inquire (assuan_context_t ctx, const char *keyword,      {        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; diff --git a/assuan/assuan-socket.c b/assuan/assuan-socket.c index 02a62253..74e8eb29 100644 --- a/assuan/assuan-socket.c +++ b/assuan/assuan-socket.c @@ -145,7 +145,10 @@ read_port_and_nonce (const char *fname, unsigned short *port, char *nonce)  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 @@ _assuan_close (assuan_fd_t fd)  #else    return close (fd);  #endif +#endif  } @@ -173,13 +177,25 @@ _assuan_sock_new (int domain, int type, int proto)    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 @@ _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)        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 @@ _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)                ret = -1;              }          } +      else +        errno = _assuan_sock_wsa2errno (WSAGetLastError ());        return ret;      }    else @@ -231,8 +256,14 @@ _assuan_sock_connect (assuan_fd_t sockfd, struct sockaddr *addr, int addrlen)        return res;      }        #else + +#ifdef _ASSUAN_CUSTOM_IO +  return _assuan_custom_connect (sockfd, addr, addrlen); +#else    return connect (sockfd, addr, addrlen);  #endif + +#endif  } diff --git a/assuan/assuan.h b/assuan/assuan.h index 4cf6a034..971ff4d9 100644 --- a/assuan/assuan.h +++ b/assuan/assuan.h @@ -77,6 +77,7 @@ int _gpgme_io_read (int fd, void *buffer, size_t count);  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 @@ int _gpgme_io_recvmsg (int sock, struct msghdr *msg, int flags);  #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. ******/ diff --git a/src/ChangeLog b/src/ChangeLog index 307543a1..3a570f5a 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,22 @@ +2009-04-08  Marcus Brinkmann  <[email protected]> + +	* 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  <[email protected]>  	* gpgme.h.in (GPGME_KEYLIST_MODE_EPHEMERAL): New. diff --git a/src/engine-assuan.c b/src/engine-assuan.c index bfe7a037..12de042f 100644 --- a/src/engine-assuan.c +++ b/src/engine-assuan.c @@ -415,7 +415,18 @@ llass_status_handler (void *opaque, int fd)        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));  	} diff --git a/src/version.c b/src/version.c index 03d9e9ae..c6fb52b9 100644 --- a/src/version.c +++ b/src/version.c @@ -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 @@ do_subsystem_inits (void)    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); diff --git a/src/w32-glib-io.c b/src/w32-glib-io.c index c646edcf..5f8c8867 100644 --- a/src/w32-glib-io.c +++ b/src/w32-glib-io.c @@ -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,20 +109,96 @@ static struct  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;  } @@ -123,7 +206,7 @@ find_channel (int fd, int create)  void *  gpgme_get_giochannel (int fd)  { -  return find_channel (fd, 0); +  return find_channel (fd);  } @@ -131,7 +214,7 @@ gpgme_get_giochannel (int fd)  void *  gpgme_get_fdptr (int fd)  { -  return find_channel (fd, 0); +  return find_channel (fd);  } @@ -141,9 +224,17 @@ gpgme_get_fdptr (int fd)  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 @@ _gpgme_io_read (int fd, void *buffer, size_t count)    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,14 +283,20 @@ _gpgme_io_read (int fd, void *buffer, size_t count)    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;      } - -  TRACE_LOGBUF (buffer, nread); +   +  if (nread != 0 && nread != -1) +    TRACE_LOGBUF (buffer, nread);    errno = saved_errno;    return TRACE_SYSRES (nread); @@ -213,11 +310,13 @@ _gpgme_io_write (int fd, const void *buffer, size_t count)    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,8 +325,19 @@ _gpgme_io_write (int fd, const void *buffer, size_t count)      }    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; @@ -241,13 +351,14 @@ _gpgme_io_write (int fd, const void *buffer, size_t count)  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 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)      {        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 @@ _gpgme_io_pipe (int filedes[2], int inherit_idx)      {        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 -     should have a giochannel.  */ -  chan = find_channel (filedes[1 - inherit_idx], 1); -  if (!chan) +  /* 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 (filedes[0]); -      _close (filedes[1]); +       +      _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.  */ +  filedes[1 - inherit_idx] = new_channel_from_fd (fds[1 - inherit_idx]); +  if (filedes[1 - inherit_idx] < 0) +    { +      int saved_errno = errno; +       +      _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 @@ _gpgme_io_close (int fd)        return TRACE_SYSRES (-1);      } +  assert (giochannel_table[fd].used); +    /* First call the notify handler.  */    if (notify_table[fd].handler)      { @@ -318,19 +446,26 @@ _gpgme_io_close (int fd)        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 @@ _gpgme_io_set_nonblocking (int fd)    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 @@ _gpgme_io_spawn (const char *path, char * const argv[],        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 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)  	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 @@ _gpgme_io_dup (int fd)  {    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 (); +} diff --git a/src/w32-io.c b/src/w32-io.c index 1f62a6f1..1a65e537 100644 --- a/src/w32-io.c +++ b/src/w32-io.c @@ -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 @@ gpgme_get_fdptr (int fd)  {    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 (); +} diff --git a/src/w32-qt-io.cpp b/src/w32-qt-io.cpp index 681493ff..08f780f1 100644 --- a/src/w32-qt-io.cpp +++ b/src/w32-qt-io.cpp @@ -674,3 +674,20 @@ _gpgme_io_dup (int fd)      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; +} | 
