+2008-04-20 Dan Winship <danw@gnome.org>
+
+ Fixes for GnuTLS support on Win32. #528752, patch from Marc Maurer
+
+ * libsoup/soup-gnutls.c (soup_ssl_wrap_iochannel): add an argument
+ saying whether or not the socket is non-blocking, since there's no
+ way to determine this from the fd in WinSock.
+ (do_handshake, soup_gnutls_read, soup_gnutls_write): Update for
+ that.
+
+ * libsoup/soup-socket.c (soup_socket_start_proxy_ssl): Update for
+ that
+
+ * libsoup/soup-nossl.c (soup_ssl_wrap_iochannel): update the
+ declaration here too
+
+ * tests/ssl-test.c: Some updates to get this closer to working on
+ Windows...
+
2008-04-14 Chris Lord <chrislord.net@gmail.com>
reviewed by: Dan Winship <danw@gnome.org>
#include <errno.h>
#include <fcntl.h>
-#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <glib.h>
+#ifndef G_OS_WIN32
+#include <pthread.h>
+#endif
+
#include <gcrypt.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
GIOChannel channel;
int fd;
GIOChannel *real_sock;
+ gboolean non_blocking;
gnutls_session session;
SoupSSLCredentials *creds;
char *hostname;
return TRUE;
}
-#define SOUP_GNUTLS_CHANNEL_NONBLOCKING(chan) (fcntl ((chan)->fd, F_GETFL, 0) & O_NONBLOCK)
-
static GIOStatus
do_handshake (SoupGNUTLSChannel *chan, GError **err)
{
result = gnutls_handshake (chan->session);
if (result == GNUTLS_E_AGAIN || result == GNUTLS_E_INTERRUPTED) {
- if (SOUP_GNUTLS_CHANNEL_NONBLOCKING (chan)) {
+ if (chan->non_blocking) {
g_set_error (err, SOUP_SSL_ERROR,
(gnutls_record_get_direction (chan->session) ?
SOUP_SSL_ERROR_HANDSHAKE_NEEDS_WRITE :
}
if (result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN) {
- if (SOUP_GNUTLS_CHANNEL_NONBLOCKING (chan))
+ if (chan->non_blocking)
return G_IO_STATUS_AGAIN;
else
goto again;
}
if (result == GNUTLS_E_INTERRUPTED || result == GNUTLS_E_AGAIN) {
- if (SOUP_GNUTLS_CHANNEL_NONBLOCKING (chan))
+ if (chan->non_blocking)
return G_IO_STATUS_AGAIN;
else
goto again;
/**
* soup_ssl_wrap_iochannel:
* @sock: a #GIOChannel wrapping a TCP socket.
+ * @non_blocking: whether the underlying socket is blocking or not
* @type: whether this is a client or server socket
* @remote_host: the hostname of the remote machine
* @creds: a client or server credentials structure
* failure.
**/
GIOChannel *
-soup_ssl_wrap_iochannel (GIOChannel *sock, SoupSSLType type,
- const char *remote_host, SoupSSLCredentials *creds)
+soup_ssl_wrap_iochannel (GIOChannel *sock, gboolean non_blocking,
+ SoupSSLType type, const char *remote_host,
+ SoupSSLCredentials *creds)
{
SoupGNUTLSChannel *chan = NULL;
GIOChannel *gchan = NULL;
chan->creds = creds;
chan->hostname = g_strdup (remote_host);
chan->type = type;
+ chan->non_blocking = non_blocking;
g_io_channel_ref (sock);
gchan = (GIOChannel *) chan;
return NULL;
}
-#ifdef GCRY_THREAD_OPTION_PTHREAD_IMPL
+#if defined(GCRY_THREAD_OPTION_PTHREAD_IMPL) && !defined(G_OS_WIN32)
GCRY_THREAD_OPTION_PTHREAD_IMPL;
#endif
static volatile gsize inited_gnutls = 0;
if (g_once_init_enter (&inited_gnutls)) {
-#ifdef GCRY_THREAD_OPTION_PTHREAD_IMPL
+#if defined(GCRY_THREAD_OPTION_PTHREAD_IMPL) && !defined(G_OS_WIN32)
gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
#endif
gnutls_global_init ();
const gboolean soup_ssl_supported = FALSE;
GIOChannel *
-soup_ssl_wrap_iochannel (GIOChannel *sock, SoupSSLType type,
- const char *hostname, SoupSSLCredentials *creds)
+soup_ssl_wrap_iochannel (GIOChannel *sock, gboolean non_blocking,
+ SoupSSLType type, const char *hostname,
+ SoupSSLCredentials *creds)
{
return NULL;
}
#include <config.h>
#endif
+#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
real_chan = priv->iochannel;
ssl_chan = soup_ssl_wrap_iochannel (
- real_chan, priv->is_server ?
+ real_chan, priv->non_blocking, priv->is_server ?
SOUP_SSL_TYPE_SERVER : SOUP_SSL_TYPE_CLIENT,
ssl_host, priv->ssl_creds);
void soup_ssl_free_server_credentials (SoupSSLCredentials *creds);
GIOChannel *soup_ssl_wrap_iochannel (GIOChannel *sock,
+ gboolean non_blocking,
SoupSSLType type,
const char *remote_host,
SoupSSLCredentials *creds);
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
#include "libsoup/soup-address.h"
#include "libsoup/soup-socket.h"
#define BUFSIZE 1024
#define DH_BITS 1024
+#ifndef G_OS_WIN32
+#define SOCKET_PRINT_ERROR(M) perror(M);
+#else
+#define SOCKET_PRINT_ERROR(M) g_error("%s: %d", M, WSAGetLastError());
+#endif
+
static GMainLoop *loop;
static gnutls_dh_params_t dh_params;
}
}
-static const char *ssl_cert_file = SRCDIR "/test-cert.pem";
-static const char *ssl_key_file = SRCDIR "/test-key.pem";
+static const char *ssl_cert_file = SRCDIR G_DIR_SEPARATOR_S "test-cert.pem";
+static const char *ssl_key_file = SRCDIR G_DIR_SEPARATOR_S "test-key.pem";
static gpointer
server_thread (gpointer user_data)
g_thread_init (NULL);
g_type_init ();
+ /* On Windows, this will call WSAStartup() */
+ soup_address_get_type ();
+
while ((opt = getopt (argc, argv, "c:d:k:")) != -1) {
switch (opt) {
case 'c':
/* Create server socket */
listener = socket (AF_INET, SOCK_STREAM, 0);
if (listener == -1) {
- perror ("creating listening socket");
+ SOCKET_PRINT_ERROR ("creating listening socket");
exit (1);
}
sin.sin_addr.s_addr = INADDR_ANY;
if (bind (listener, (struct sockaddr *) &sin, sizeof (sin)) == -1) {
- perror ("binding listening socket");
+ SOCKET_PRINT_ERROR ("binding listening socket");
exit (1);
}
if (listen (listener, 1) == -1) {
- perror ("listening on socket");
+ SOCKET_PRINT_ERROR ("listening on socket");
exit (1);
}