2009-04-08  Marcus Brinkmann  <marcus@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@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.
This commit is contained in:
Marcus Brinkmann 2009-04-08 18:53:57 +00:00
parent 6f8aa0e29d
commit d255b4bec9
14 changed files with 504 additions and 79 deletions

7
TODO
View File

@ -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

View File

@ -1,3 +1,16 @@
2009-04-08 Marcus Brinkmann <marcus@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@g10code.de>
* assuan.h: Add prefix macros for _assuan_close and _assuan_usleep.

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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
}

View File

@ -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. ******/

View File

@ -1,3 +1,22 @@
2009-04-08 Marcus Brinkmann <marcus@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@g10code.com>
* gpgme.h.in (GPGME_KEYLIST_MODE_EPHEMERAL): New.

View File

@ -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));
}

View File

@ -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);

View File

@ -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 ();
}

View File

@ -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 ();
}

View File

@ -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;
}