diff options
author | sandmann <sandmann> | 2007-01-12 04:58:47 +0000 |
---|---|---|
committer | sandmann <sandmann> | 2007-01-12 04:58:47 +0000 |
commit | 81d6c3f502b896123a28e1daa4a891b69e8e1e71 (patch) | |
tree | d88710ece378c079ba86257ebc575c11cdfee0a7 | |
parent | 629038b8dbafaaa92478b78694da32789050c3c5 (diff) |
*** empty log message ***
-rwxr-xr-x | configure.in | 12 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/lac.h | 111 | ||||
-rw-r--r-- | src/lacbytequeue.c | 230 | ||||
-rw-r--r-- | src/lacconnection.c | 294 | ||||
-rw-r--r-- | src/lacdebug.c | 3 | ||||
-rw-r--r-- | src/lachttp.c | 4 | ||||
-rw-r--r-- | src/lacinternals.h | 25 | ||||
-rw-r--r-- | src/lacprimitives.c | 225 | ||||
-rw-r--r-- | src/lactls.c | 267 |
10 files changed, 711 insertions, 464 deletions
diff --git a/configure.in b/configure.in index f523151..c52175d 100755 --- a/configure.in +++ b/configure.in @@ -38,7 +38,7 @@ if test "x$GCC" = "xyes"; then fi #LIBS="$LIBS `glib-config --libs`" -CFLAGS="$CFLAGS -D_REENTRANT" +#CFLAGS="$CFLAGS -D_REENTRANT" AC_CHECK_FUNC(connect,,AC_CHECK_LIB(socket, connect)) AC_CHECK_FUNC(inet_aton,,AC_CHECK_LIB(resolv, inet_aton)) @@ -140,12 +140,10 @@ AC_CHECK_FUNC(gethostbyname_r, ]) dnl Checks for libraries. -AM_PATH_GLIB_2_0(2.0.0, - [LIBS="$LIBS $GLIB_LIBS" CFLAGS="$CFLAGS $GLIB_CFLAGS"], - AC_MSG_ERROR([ -*** GLIB 1.3.1 or better is required. The latest version of GLIB -*** is always available from ftp://ftp.gtk.org/.]), -) +PKG_CHECK_MODULES(DEP, glib-2.0 gnutls >= 1.4) + +LIBS="$LIBS $DEP_LIBS" +CFLAGS="$CFLAGS $DEP_CFLAGS" dnl Checks for header files. AC_HEADER_STDC diff --git a/src/Makefile.am b/src/Makefile.am index 5364b72..3307a06 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,19 +8,19 @@ lacinclude_HEADERS= \ lac.h liblac_1_la_SOURCES = \ + lacaddress.c \ lacprimitives.c \ lacwatch.c \ + lacbytequeue.c \ lacdebug.c \ lacdns-config.c \ lacdns-query.c \ lacdns-messages.c \ lacdns-cache.c \ lacdns-nameserver.c \ - lacaddress.c \ lacuri.c \ lacconnection.c \ lachttp.c \ - lactls.c \ \ lacinternals.h \ lacdns-messages.h \ @@ -1,7 +1,8 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */ /* Lac - Library for asynchronous communication - * Copyright (C) 2000, 2001, 2002, 2003 Søren Sandmann (sandmann@daimi.au.dk) + * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 + * Søren Sandmann (sandmann@daimi.au.dk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -110,10 +111,10 @@ typedef enum LAC_SOCKET_ERROR_NET_UNREACHABLE, LAC_SOCKET_ERROR_TIMEOUT, LAC_SOCKET_ERROR_CONNECTION_RESET, - + LAC_SOCKET_ERROR_NO_RESOURCES, LAC_SOCKET_ERROR_AGAIN, /* also known as WOULDBLOCK */ - + LAC_SOCKET_ERROR_FAILED } LacError; @@ -182,6 +183,58 @@ gboolean lac_getpeername (gint fd, GError **err); gchar * lac_gethostname (void); +/* LacByteQueue */ +typedef struct LacByteQueue LacByteQueue; + +LacByteQueue *lac_byte_queue_new (void); +guint8 *lac_byte_queue_free (LacByteQueue *queue, + gboolean free_data); +gsize lac_byte_queue_get_length (LacByteQueue *queue); +const guint8 *lac_byte_queue_get_data (LacByteQueue *queue, + gsize *n_bytes); +void lac_byte_queue_put_back (LacByteQueue *queue, + const guint8 *bytes, + gsize n_bytes); +void lac_byte_queue_append (LacByteQueue *queue, + const guint8 *bytes, + gsize n_bytes); +guint8 *lac_byte_queue_alloc_tail (LacByteQueue *queue, + gsize size); +void lac_byte_queue_delete_tail (LacByteQueue *queue, + gsize size); +void lac_byte_queue_steal_data (LacByteQueue *dest, + LacByteQueue *src); + + +/* TLS */ +typedef struct LacTLS LacTLS; + +typedef int (* LacTLSSendFunc) (LacTLS *tls, + const guint8 *data, + gsize len, + GError **err); +typedef int (* LacTLSRecvFunc) (LacTLS *tls, + guint8 *data, + gsize buf_size, + GError **err); +LacTLS *lac_tls_new (int fd); +LacTLS *lac_tls_new2 (LacTLSSendFunc send_func, + LacTLSRecvFunc recv_func, + gpointer data); +gpointer lac_tls_get_data (LacTLS *tls); +gboolean lac_tls_handshake (LacTLS *tls, + GError **err); +gint lac_tls_recv (LacTLS *tls, + gchar *buf, + guint len, + GError **err); +gint lac_tls_send (LacTLS *tls, + gchar *buf, + guint len, + GError **err); +gboolean lac_tls_needs_write (LacTLS *tls); +void lac_tls_free (LacTLS *tls); + /* * Watching file descriptors @@ -203,35 +256,6 @@ void lac_fd_set_priority_callback (gint fd, void lac_fd_remove_watch (gint fd); gboolean lac_fd_is_watched (gint fd); - -/* - * TLS - */ -typedef struct LacTLS LacTLS; - -LacTLS * lac_tls_new (GError **err); -void lac_tls_connect (LacTLS *tls); -void lac_tls_set_read_callback (LacTLS *tls, - LacWatchCallback read_cb); -void lac_tls_set_write_callback (LacTLS *tls, - LacWatchCallback write_cb); -void lac_tls_set_hangup_callback (LacTLS *tls, - LacWatchCallback hangup_cb); -void lac_tls_set_error_callback (LacTLS *tls, - LacWatchCallback error_cb); -void lac_tls_set_priority_callback (LacTLS *tls, - LacWatchCallback priority_cb); -int lac_tls_send (LacTLS *tls, - char *msg, - guint len, - GError **err); -int lac_tls_recv (LacTLS *tls, - char *buf, - guint size, - GError **err); -gboolean lac_tls_free (LacTLS *tls, - GError **err); - /* * Connection */ @@ -342,7 +366,7 @@ struct _LacUri { } ftp; } u; gchar *fragment; - + guint checksum; /* used internally */ }; @@ -477,29 +501,8 @@ union _LacHttpEvent { LacHttpErrorEvent error; }; - -/* - * Debug spew - */ -#define lac_debug_out(format,args...) G_STMT_START{ \ - char *lac_debug_temp_pointer; \ - if (lac_is_verbose()) \ - { \ - lac_debug_temp_pointer = g_strdup_printf (format, args); \ - g_log ("lac-debug", \ - G_LOG_LEVEL_MESSAGE, \ - "file %s: line %d (%s): %s", \ - __FILE__, \ - __LINE__, \ - __PRETTY_FUNCTION__, \ - lac_debug_temp_pointer); \ - g_free (lac_debug_temp_pointer); \ - } \ -} G_STMT_END - /* make LAC write lots of spam to stdout */ void lac_set_verbose (gboolean verbose); -gboolean lac_is_verbose (void); #define lac_debug_checkpoint() lac_debug_out ("reached%s", "") diff --git a/src/lacbytequeue.c b/src/lacbytequeue.c index b8965db..16eaa6a 100644 --- a/src/lacbytequeue.c +++ b/src/lacbytequeue.c @@ -1,91 +1,215 @@ -struct _LacByteQueue -{ - guint allocated; - - guint8 * data; - guint8 * head; - guint8 * tail; -}; +#include <string.h> +#include "lac.h" -enum { - INITIAL_SIZE = 256 +struct LacByteQueue +{ + gsize segment_size; + guint8 * segment; + guint8 * start; + guint8 * end; }; LacByteQueue * lac_byte_queue_new (void) { - LacByteQueue *byte_queue = g_new (LacByteQueue, 1); - - byte_queue->allocated = INITIAL_SIZE; - - byte_queue->data = g_new (guint8, INITIAL_SIZE); - byte_queue->head = byte_queue->data; - byte_queue->tail = byte_queue->data; + LacByteQueue *queue = g_new0 (LacByteQueue, 1); + + queue->segment_size = 0; + queue->segment = NULL; + queue->start = NULL; + queue->end = NULL; + + return queue; +} - return byte_queue; +guint8 * +lac_byte_queue_free (LacByteQueue *queue, + gboolean free_data) +{ + guint8 *result; + + if (free_data) + { + g_free (queue->segment); + + result = NULL; + } + else + { + memmove (queue->segment, queue->start, queue->end - queue->start); + + result = queue->segment; + } + + g_free (queue); + + return result; } -guint -lac_byte_queue_get_length (LacByteQueue *byte_queue) +/* The data returned is owned by the byte queue and becomes invalid + * as soon as any method is called on the queue. It is explicitly + * allowed to push the returned data back into the queue, and indeed + * in that case the queue will avoid copying if it can. The push + * must be the first method called on the queue after the read. + */ +const guint8 * +lac_byte_queue_get_data (LacByteQueue *queue, + gsize *n_bytes) { - return byte_queue->tail - byte_queue->head; + guint8 *result; + + if (n_bytes) + *n_bytes = queue->end - queue->start; + + result = queue->start; + + queue->start = queue->segment; + queue->end = queue->segment; + + return result; } -static guint -lac_byte_queue_get_capacity (LacByteQueue *byte_queue) +static gboolean +in_segment (LacByteQueue *queue, + const guint8 *bytes, + gsize n_bytes) { - return byte_queue->allocated - lac_byte_queue_get_length (byte_queue); + return bytes >= queue->segment && bytes + n_bytes < queue->end; } -static guint -power_of_two_bigger_than (guint n) +static gboolean +is_empty (LacByteQueue *queue) { - guint result = 1; + return queue->start == queue->end; +} +static gsize +power_of_two_bigger_than (gsize n) +{ + gsize result = 1; + while (result <= n) result *= 2; - + return result; } static void -lac_byte_queue_ensure_capacity (LacByteQueue *byte_queue, guint needed) +ensure_room (LacByteQueue *queue, + gsize extra) { - guint new_size; + gsize old_data_size = queue->end - queue->start; + gsize new_data_size = old_data_size + extra; - if (needed <= lac_byte_queue_get_capacity (byte_queue)) - return; + if (queue->end + new_data_size > queue->segment + queue->segment_size) + { + gsize new_segment_size = power_of_two_bigger_than (2 * new_data_size); + + memmove (queue->start, queue->segment, old_data_size); + + if (new_segment_size > queue->segment_size) + { + queue->segment_size = new_segment_size; + queue->segment = g_realloc (queue->segment, new_segment_size); + } + + queue->start = queue->segment; + queue->end = queue->start + new_data_size; + } +} - new_size = power_of_two_bigger_than (needed); +/* This function appends uninitialized data of length @size + * to the queue, then returns a pointer to the added data. + * The intention is that the app can read() into this + * memory, then use lac_byte_queue_pop_tail() to delete the + * area that wasn't read into. Example + * + * guint8 *area = lac_byte_queue_alloc_tail (queue, 8192); + * + * n_read = read (fd, area, 8192); + * + * lac_byte_queue_delete_tail (queue, 8192 - (n_read < 0)? 0 : n_read); + * + * if (n_read < 0) + * { + * lac_byte_queue_delete_tail (queue, 8192); + * handle_error(); + * n_read = 0; + * } + * else + * { + * lac_byte_queue_delete_tail (8192 - n_read); + * + * // enjoy the new data in the queue + * } + */ +guint8 * +lac_byte_queue_alloc_tail (LacByteQueue *queue, + gsize size) +{ + ensure_room (queue, size); + + queue->end += size; + + return queue->end - size; } void -lac_byte_queue_append (LacByteQueue *byte_queue, guint8 *data, guint length) +lac_byte_queue_delete_tail (LacByteQueue *queue, + gsize size) { - guint needed_capacity = lac_byte_queue_get_length (byte_queue) + length; - - lac_byte_queue_ensure_capacity (byte_queue, needed_capacity); + if (queue->end - queue->start < size) + queue->end = queue->start; + else + queue->end -= size; +} - if (byte_queue->head >= byte_queue->tail) +void +lac_byte_queue_append (LacByteQueue *queue, + const guint8 *bytes, + gsize n_bytes) +{ + if (in_segment (queue, bytes, n_bytes) && is_empty (queue)) { - guint bytes_to_copy = MIN ( - byte_queue->data + byte_queue->allocated - byte_queue->head, - length); - - memcpy (byte_queue->head, data, bytes_to_copy); - - byte_queue->head += bytes_to_copy; - length -= bytes_to_copy; - data += bytes_to_copy; + queue->start = (guint8 *)bytes; + queue->end = (guint8 *)bytes + n_bytes; + } + else + { + guint8 *tail = lac_byte_queue_alloc_tail (queue, n_bytes); - if (byte_queue->head == byte_queue->data + byte_queue->allocated) - byte_queue->head = byte_queue->data; + memcpy (tail, bytes, n_bytes); } +} - if (length > 0) +/* Transfer data from @src to @dest, if possible without copying. + * The data is appended to @dest's data if @dest is not empty + */ +void +lac_byte_queue_steal_data (LacByteQueue *dest, + LacByteQueue *src) +{ + if (is_empty (dest)) { - memcpy (byte_queue->head, data, length); - - byte_queue->head += length; + if (dest->segment) + g_free (dest->segment); + + dest->segment_size = src->segment_size; + dest->segment = src->segment; + dest->start = src->start; + dest->end = src->end; + + src->segment_size = 0; + src->segment = NULL; + src->start = NULL; + src->end = NULL; + } + else + { + const guint8 *data; + gsize size; + + data = lac_byte_queue_get_data (src, &size); + lac_byte_queue_append (dest, data, size); } } diff --git a/src/lacconnection.c b/src/lacconnection.c index 8ec0a6a..d65c5a5 100644 --- a/src/lacconnection.c +++ b/src/lacconnection.c @@ -40,10 +40,12 @@ static gint socket_send (Socket *socket, guint len, GError **err); static gint socket_recv (Socket *socket, - gchar *buf, + guint8 *buf, guint size, GError **err); +#if 0 static int socket_get_fd (Socket *socket); +#endif static void socket_flush (Socket *socket); static gboolean socket_shutdown (Socket *socket, LacShutdownMethod how, @@ -53,7 +55,13 @@ static gboolean socket_set_blocking (Socket *socket, GError **err); static gboolean socket_close (Socket *socket, GError **err); - +static void socket_add_watch (Socket *socket, + gpointer data); +static void socket_remove_watch (Socket *socket); +static void socket_set_read_cb (Socket *socket, + LacWatchCallback read_cb); +static void socket_set_write_cb (Socket *socket, + LacWatchCallback write_cb); typedef enum { @@ -160,7 +168,7 @@ emit_events (LacConnection *connection) if (connection->has_fd) { - lac_fd_remove_watch (socket_get_fd (connection->socket)); + socket_remove_watch (connection->socket); socket_close (connection->socket, NULL); connection->has_fd = FALSE; } @@ -244,8 +252,7 @@ lac_connection_do_writes (LacConnection *connection) { if (connection->state != CONNECTED) { - lac_fd_set_write_callback ( - socket_get_fd (connection->socket), lac_connection_writable); + socket_set_write_cb (connection->socket, lac_connection_writable); return; } @@ -262,9 +269,8 @@ lac_connection_do_writes (LacConnection *connection) if (g_error_matches ( err, LAC_SOCKET_ERROR, LAC_SOCKET_ERROR_AGAIN)) { - lac_fd_set_write_callback ( - socket_get_fd (connection->socket), - lac_connection_writable); + socket_set_write_cb ( + connection->socket, lac_connection_writable); } else { @@ -279,15 +285,11 @@ lac_connection_do_writes (LacConnection *connection) /* FIXME check that we haven't used too much time? */ } - - lac_fd_set_write_callback (socket_get_fd (connection->socket), NULL); + + socket_set_write_cb (connection->socket, NULL); if (connection->need_flush) { - /* Turn Nagle off, then on, to make the kernel send everything it - * has queued up. - */ - socket_flush (connection->socket); connection->need_flush = FALSE; @@ -376,14 +378,10 @@ lac_connection_discard_pending_events (LacConnection *connection) static void lac_connection_add_watch (LacConnection *connection) { - int fd = socket_get_fd (connection->socket); - - lac_fd_add_watch (fd, connection); + socket_add_watch (connection->socket, connection); - lac_fd_set_read_callback (fd, lac_connection_readable); - lac_fd_set_hangup_callback (fd, lac_connection_readable); - lac_fd_set_error_callback (fd, lac_connection_readable); - lac_fd_set_write_callback (fd, lac_connection_writable); + socket_set_read_cb (connection->socket, lac_connection_readable); + socket_set_write_cb (connection->socket, lac_connection_writable); } LacConnection * @@ -471,7 +469,7 @@ lac_connection_write (LacConnection *connection, do_writes = (connection->unwritten->len == 0); - g_string_append_len (connection->unwritten, data, len); + g_string_append_len (connection->unwritten, (gchar *)data, len); if (do_writes) { @@ -479,6 +477,7 @@ lac_connection_write (LacConnection *connection, emit_events (connection); } } + void lac_connection_write_cstr (LacConnection *connection, const gchar *data) @@ -539,7 +538,7 @@ lac_connection_unref (LacConnection *connection) if (connection->has_fd) { - lac_fd_remove_watch (socket_get_fd (connection->socket)); + socket_remove_watch (connection->socket); socket_close (connection->socket, NULL); } @@ -580,7 +579,25 @@ lac_connection_flush (LacConnection *connection) */ struct Socket { - int fd; + gboolean ssl; + + union + { + struct + { + int fd; + } tcp; + + struct + { + int fd; + LacTLS *tls; + gboolean override; + gpointer data; + LacWatchCallback read_cb; + LacWatchCallback write_cb; + } ssl; + } u; }; static Socket * @@ -595,7 +612,29 @@ socket_new_tcp (GError **err) return NULL; socket = g_new0 (Socket, 1); - socket->fd = fd; + socket->u.ssl.tls = FALSE; + socket->u.ssl.fd = fd; + socket->u.ssl.override = FALSE; + socket->u.ssl.read_cb = NULL; + socket->u.ssl.write_cb = NULL; + + return socket; +} + +static Socket * +socket_new_ssl (GError **err) +{ + Socket *socket; + int fd; + + fd = lac_socket_tcp (err); + if (fd < 0) + return NULL; + + socket = g_new0 (Socket, 1); + socket->ssl = TRUE; + socket->u.ssl.fd = fd; + socket->u.ssl.tls = NULL; // lac_tls return socket; } @@ -606,7 +645,15 @@ socket_connect (Socket *socket, gint port, GError **err) { - return lac_connect (socket->fd, address, port, err); + if (socket->ssl) + { + lac_connect (socket->u.ssl.fd, address, port, err); + + } + else + { + return lac_connect (socket->u.tcp.fd, address, port, err); + } } static gboolean @@ -618,42 +665,129 @@ socket_is_connected (Socket *socket) return TRUE; } -static gint -socket_send (Socket *socket, - const gchar *msg, - guint len, - GError **err) +static void +set_normal_callbacks (Socket *socket) +{ + g_assert (socket->ssl); + + lac_fd_set_read_callback (socket->u.ssl.fd, socket->u.ssl.read_cb); + lac_fd_set_write_callback (socket->u.ssl.fd, socket->u.ssl.write_cb); + + socket->u.ssl.override = FALSE; +} + +static void +override_readable (gpointer data) +{ + Socket *socket = data; + + if (socket->u.ssl.read_cb) + socket->u.ssl.read_cb (socket->u.ssl.data); + + set_normal_callbacks (socket); +} + +static void +override_writable (gpointer data) +{ + Socket *socket = data; + + if (socket->u.ssl.write_cb) + socket->u.ssl.write_cb (socket->u.ssl.data); + + set_normal_callbacks (socket); +} + +static void +override_callbacks (Socket *socket, + LacWatchCallback func) { - return lac_send (socket->fd, msg, len, err); + gboolean needs_write; + + g_assert (socket->ssl); + + needs_write = lactls_needs_write (socket->u.ssl.tls); + + lac_fd_set_write_callback (socket->u.ssl.fd, needs_write? func : NULL); + lac_fd_set_read_callback (socket->u.ssl.fd, needs_write? NULL : func); + +#if 0 + socket->u.ssl.overridden = TRUE; +#endif } static gint -socket_recv (Socket *socket, - gchar *buf, - guint size, - GError **err) +socket_send (Socket *socket, + const gchar *msg, + guint len, + GError **err) { - return lac_recv (socket->fd, buf, size, err); + if (socket->ssl) + { + GError *err = NULL; + +#if 0 + lac_tls_send (socket->u.ssl.tls, msg, len, &err); +#endif + + if (err) + { +#if 0 + if (AGAIN) + override_callbacks (socket, override_writable); +#endif + } + } + else + { + return lac_send (socket->u.tcp.fd, msg, len, err); + } } -static int -socket_get_fd (Socket *socket) +static gint +socket_recv (Socket *socket, + guint8 *buf, + guint size, + GError **err) { - return socket->fd; + if (socket->ssl) + { + } + else + { + return lac_recv (socket->u.tcp.fd, (gchar *)buf, size, err); + } } static gboolean socket_close (Socket *socket, GError **err) { - return lac_close (socket->fd, err); + if (socket->ssl) + { + } + else + { + return lac_close (socket->u.tcp.fd, err); + } } static void socket_flush (Socket *socket) { - lac_set_nagle (socket->fd, FALSE, NULL); - lac_set_nagle (socket->fd, TRUE, NULL); + if (socket->ssl) + { + } + else + { + /* Turn Nagle off, then on, to make the kernel send everything it + * has queued up. + */ + + lac_set_nagle (socket->u.tcp.fd, FALSE, NULL); + lac_set_nagle (socket->u.tcp.fd, TRUE, NULL); + } + } static gboolean @@ -661,7 +795,13 @@ socket_set_blocking (Socket *socket, gboolean blocking, GError **err) { - return lac_set_blocking (socket->fd, blocking, err); + if (socket->ssl) + { + } + else + { + return lac_set_blocking (socket->u.tcp.fd, blocking, err); + } } static gboolean @@ -669,5 +809,69 @@ socket_shutdown (Socket *socket, LacShutdownMethod how, GError **err) { - return lac_shutdown (socket->fd, how, err); + if (socket->ssl) + { + } + else + { + return lac_shutdown (socket->u.tcp.fd, how, err); + } +} + +static void +socket_add_watch (Socket *socket, + gpointer data) +{ + if (socket->ssl) + { + socket->u.ssl.data = data; + lac_fd_add_watch (socket->u.ssl.fd, data); + } + else + { + lac_fd_add_watch (socket->u.tcp.fd, data); + } +} + +static void +socket_remove_watch (Socket *socket) +{ + if (socket->ssl) + { + socket->u.ssl.data = NULL; + lac_fd_remove_watch (socket->u.ssl.fd); + } + else + { + lac_fd_remove_watch (socket->u.tcp.fd); + } +} + +static void +socket_set_read_cb (Socket *socket, + LacWatchCallback read_cb) +{ + if (socket->ssl) + { + } + else + { + lac_fd_set_read_callback (socket->u.tcp.fd, read_cb); + lac_fd_set_hangup_callback (socket->u.tcp.fd, read_cb); + lac_fd_set_error_callback (socket->u.tcp.fd, read_cb); + lac_fd_set_write_callback (socket->u.tcp.fd, read_cb); + } +} + +static void +socket_set_write_cb (Socket *socket, + LacWatchCallback write_cb) +{ + if (socket->ssl) + { + } + else + { + lac_fd_set_write_callback (socket->u.tcp.fd, write_cb); + } } diff --git a/src/lacdebug.c b/src/lacdebug.c index 94ce8b0..0bd87cf 100644 --- a/src/lacdebug.c +++ b/src/lacdebug.c @@ -1,7 +1,7 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */ /* Lac - Library for asynchronous communication - * Copyright (C) 2000, 2001 Søren Sandmann + * Copyright (C) 2000, 2001, 2007 Søren Sandmann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -20,6 +20,7 @@ */ #include "lac.h" +#include "lacinternals.h" static gboolean lac_verbose = FALSE; diff --git a/src/lachttp.c b/src/lachttp.c index ede15ec..60f10c3 100644 --- a/src/lachttp.c +++ b/src/lachttp.c @@ -1928,7 +1928,9 @@ server_choked_on_pipeline (HttpTransport *transport, guint recover_time) * giving up on pipelining completely) * * The alternative: report back to the user that the data - * he already received was useless, is not nice. + * he already received was useless, is not nice. FIXME: + * hmm, why not? Just tell the application that the request + * failed and it should retry. Seems a lot simpler to me ... */ LacHttpRequest *request = transport->current; gsize n_bytes; diff --git a/src/lacinternals.h b/src/lacinternals.h index 52fea0b..6953391 100644 --- a/src/lacinternals.h +++ b/src/lacinternals.h @@ -1,7 +1,7 @@ /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- */ /* Lac - Library for asynchronous communication - * Copyright (C) 2002 Søren Sandmann (sandmann@daimi.au.dk) + * Copyright (C) 2002, 2007 Søren Sandmann (sandmann@daimi.au.dk) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -49,4 +49,27 @@ void lac_address_get_in_addr (const LacAddress *addr, struct in_addr *in_addr); void lac_address_set_in_addr (LacAddress *addr, struct in_addr *in_addr); + + +/* + * Debug spew + */ +#define lac_debug_out(format,args...) G_STMT_START{ \ + char *lac_debug_temp_pointer; \ + if (lac_is_verbose()) \ + { \ + lac_debug_temp_pointer = g_strdup_printf (format, args); \ + g_log ("lac-debug", \ + G_LOG_LEVEL_MESSAGE, \ + "file %s: line %d (%s): %s", \ + __FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__, \ + lac_debug_temp_pointer); \ + g_free (lac_debug_temp_pointer); \ + } \ + } G_STMT_END + +gboolean lac_is_verbose (void); + #endif /* LAC_INTERNALS_H */ diff --git a/src/lacprimitives.c b/src/lacprimitives.c index d75b2ae..4ffb122 100644 --- a/src/lacprimitives.c +++ b/src/lacprimitives.c @@ -67,9 +67,15 @@ extern gint h_errno; #include "lacinternals.h" -static void lac_set_error_from_errno (GError **err, - gint eno, - const gchar *msg); +#include <gnutls/gnutls.h> + +static void set_error_from_errno (GError **err, + gint eno, + const gchar *msg); +static void set_error_from_gnutls_error (GError **err, + int gnutls_err, + const gchar *msg); + GQuark lac_socket_error_quark (void) @@ -151,7 +157,7 @@ lac_socket_tcp (GError **err) if (fd < 0) { - lac_set_error_from_errno (err, errno, "socket() failed %s"); + set_error_from_errno (err, errno, "socket() failed %s"); return -1; } @@ -174,7 +180,7 @@ lac_socket_udp (GError **err) if (fd < 0) { - lac_set_error_from_errno (err, errno, "socket() failed: %d"); + set_error_from_errno (err, errno, "socket() failed: %d"); return -1; } @@ -211,7 +217,7 @@ lac_connect (gint fd, if (res < 0) { - lac_set_error_from_errno (err, errno, "connect() failed: %s"); + set_error_from_errno (err, errno, "connect() failed: %s"); return FALSE; } @@ -249,7 +255,7 @@ lac_bind (gint fd, if (ret < 0) { - lac_set_error_from_errno (err, errno, "bind() failed: %s"); + set_error_from_errno (err, errno, "bind() failed: %s"); return FALSE; } @@ -276,9 +282,10 @@ lac_listen (gint fd, if (ret < 0) { - lac_set_error_from_errno (err, errno, "listen() failed: %s"); + set_error_from_errno (err, errno, "listen() failed: %s"); return FALSE; } + return TRUE; } @@ -291,7 +298,7 @@ lac_accept (gint fd, guint addr_len = sizeof (struct sockaddr_in); struct sockaddr_in host_addr; gint ret; - + g_return_val_if_fail (fd > 0, FALSE); g_return_val_if_fail (err == NULL || *err == NULL, FALSE); @@ -304,16 +311,16 @@ lac_accept (gint fd, if (ret < 0) { - lac_set_error_from_errno (err, errno, "accept() failed: %s"); + set_error_from_errno (err, errno, "accept() failed: %s"); return -1; } - + if (address) { *address = lac_address_allocate (); lac_address_set_in_addr (*address, &host_addr.sin_addr); } - + if (port) *port = g_ntohs (host_addr.sin_port); @@ -340,7 +347,7 @@ lac_send (gint fd, if (res < 0) { - lac_set_error_from_errno (err, errno, "send() failed: %s:"); + set_error_from_errno (err, errno, "send() failed: %s:"); return -1; } if (res == 0) @@ -370,10 +377,10 @@ lac_recv (gint fd, if (res < 0) { - lac_set_error_from_errno (err, errno, "recv() failed: %s"); + set_error_from_errno (err, errno, "recv() failed: %s"); return -1; } - + return res; } @@ -408,10 +415,10 @@ lac_sendto (gint fd, if (res < 0) { - lac_set_error_from_errno (err, errno, "sendto() failed: %s"); + set_error_from_errno (err, errno, "sendto() failed: %s"); return FALSE; } - + return res; } @@ -430,7 +437,7 @@ lac_recvfrom (gint fd, g_return_val_if_fail (fd > 0, -1); g_return_val_if_fail (buf != NULL, -1); g_return_val_if_fail (err == NULL || *err == NULL, -1); - + errno = 0; do { @@ -442,10 +449,10 @@ lac_recvfrom (gint fd, if (res < 0) { - lac_set_error_from_errno (err, errno, "sendto() failed: %s"); + set_error_from_errno (err, errno, "sendto() failed: %s"); return -1; } - + if (address) { *address = lac_address_allocate (); @@ -453,10 +460,10 @@ lac_recvfrom (gint fd, } if (port) *port = host_addr.sin_port; - + return res; } - + gboolean lac_getpeername (gint fd, LacAddress **addr, @@ -479,7 +486,7 @@ lac_getpeername (gint fd, if (res < 0) { - lac_set_error_from_errno (err, errno, "getpeername() failed: %s"); + set_error_from_errno (err, errno, "getpeername() failed: %s"); if (addr) *addr = NULL; if (port) @@ -517,7 +524,7 @@ lac_shutdown (gint fd, if (res < 0) { - lac_set_error_from_errno (err, errno, "shutdown() failed: %s"); + set_error_from_errno (err, errno, "shutdown() failed: %s"); return FALSE; } @@ -535,14 +542,14 @@ lac_close (gint fd, g_warning ("Closing a filedescriptor with a watch attached"); errno = 0; - + /* It is actually not right to retry the close if we get EINTR. * If a signal arrives, the file descriptor is left in an indeterminate * state. The best we can do is leak it and return an error */ if (close (fd) < 0) { - lac_set_error_from_errno (err, errno, "close() failed: %s"); + set_error_from_errno (err, errno, "close() failed: %s"); return FALSE; } @@ -569,7 +576,7 @@ lac_set_blocking (gint fd, if (flags == -1) { - lac_set_error_from_errno (err, errno, "fcntl() failed: %s"); + set_error_from_errno (err, errno, "fcntl() failed: %s"); return FALSE; } @@ -593,7 +600,7 @@ lac_set_blocking (gint fd, if (ret == -1) { - lac_set_error_from_errno (err, errno, "fcntl() failed: %s"); + set_error_from_errno (err, errno, "fcntl() failed: %s"); return FALSE; } @@ -612,13 +619,165 @@ lac_set_nagle (gint fd, if (setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, &op, sizeof (op)) < 0) { - lac_set_error_from_errno (err, errno, "setsockopt() failed: %s"); + set_error_from_errno (err, errno, "setsockopt() failed: %s"); return FALSE; } return TRUE; } +struct LacTLS +{ + gnutls_anon_client_credentials_t anoncred; + gnutls_session_t session; + +}; + +static void +init (void) +{ + static gboolean initialized; + + if (!initialized) + gnutls_global_init (); +} + +LacTLS * +lac_tls_new (int fd) +{ + LacTLS *tls; + const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; + + init (); + + tls = g_new0 (LacTLS, 1); + + gnutls_anon_allocate_client_credentials (&tls->anoncred); + gnutls_init (&tls->session, GNUTLS_CLIENT); + gnutls_set_default_priority (tls->session); + gnutls_kx_set_priority (tls->session, kx_prio); + gnutls_credentials_set (tls->session, + GNUTLS_CRD_ANON, &tls->anoncred); + + gnutls_transport_set_ptr (tls->session, (gnutls_transport_ptr_t) fd); + + return tls; +} + +gboolean +lac_tls_handshake (LacTLS *tls, + GError **err) +{ + gint res; + + g_return_val_if_fail (tls != NULL, FALSE); + g_return_val_if_fail (err == NULL || *err == NULL, -1); + + errno = 0; + + do + { + res = gnutls_handshake (tls->session); + } + while (res == GNUTLS_E_INTERRUPTED); + + if (res < 0) + { + set_error_from_gnutls_error (err, res, "gnutls_handshake"); + return FALSE; + } + + return TRUE; +} + +gint +lac_tls_recv (LacTLS *tls, + gchar *buf, + guint len, + GError **err) +{ + gint res; + + g_return_val_if_fail (tls != NULL, -1); + g_return_val_if_fail (buf != 0, -1); + g_return_val_if_fail (err == NULL || *err == NULL, -1); + + errno = 0; + + do + { + res = gnutls_record_recv (tls->session, buf, len); + } + while (res == GNUTLS_E_INTERRUPTED); + + if (res < 0) + { + set_error_from_gnutls_error (err, res, "gnutls_record_recv() failed:"); + return -1; + } + + return res; +} + +gint +lac_tls_send (LacTLS *tls, + gchar *buf, + guint len, + GError **err) +{ + gint res; + + g_return_val_if_fail (tls != NULL, -1); + g_return_val_if_fail (buf != 0, -1); + g_return_val_if_fail (err == NULL || *err == NULL, -1); + + errno = 0; + do + { + res = gnutls_record_recv (tls->session, buf, len); + } + while (res != GNUTLS_E_INTERRUPTED); + + if (res < 0) + { + set_error_from_gnutls_error (err, res, "gnutls_record_send() failed:"); + return -1; + } + + return res; +} + +gboolean +lac_tls_needs_write (LacTLS *tls) +{ + g_return_val_if_fail (tls != NULL, FALSE); + + if (gnutls_record_get_direction (tls->session)) + return TRUE; + else + return FALSE; +} + +void +lac_tls_free (LacTLS *tls) +{ + gnutls_deinit (tls->session); + + gnutls_anon_free_client_credentials (tls->anoncred); + + g_free (tls); +} + +static void +set_error_from_gnutls_error (GError **err, + int gnutls_err, + const gchar *msg) +{ + /* FIXME */ + + g_set_error (err, LAC_SOCKET_ERROR, LAC_SOCKET_ERROR_FAILED, msg); +} + static LacError lac_error_from_errno (int eno) { @@ -635,7 +794,7 @@ lac_error_from_errno (int eno) return LAC_SOCKET_ERROR_TIMEOUT; break; #endif - + #ifdef ECONNRESET case ECONNRESET: return LAC_SOCKET_ERROR_CONNECTION_RESET; @@ -685,9 +844,9 @@ lac_error_from_errno (int eno) } static void -lac_set_error_from_errno (GError **err, - int eno, - const gchar *msg) +set_error_from_errno (GError **err, + int eno, + const gchar *msg) { g_set_error (err, LAC_SOCKET_ERROR, diff --git a/src/lactls.c b/src/lactls.c deleted file mode 100644 index 6689674..0000000 --- a/src/lactls.c +++ /dev/null @@ -1,267 +0,0 @@ -#include "lac.h" - -#include <gnutls/gnutls.h> - -struct LacTLS -{ - int fd; - - LacWatchCallback read_cb; - LacWatchCallback write_cb; - LacWatchCallback hangup_cb; - LacWatchCallback error_cb; - LacWatchCallback priority_cb; - -}; - -LacTLS * -lac_tls_new (GError **err) -{ - int fd; - LacTLS *tls; - - fd = lac_socket_tcp (err); - - if (fd < 0) - return NULL; - - tls = g_new0 (LacTLS, 1); - tls->fd = fd; - - return tls; -} - -static void -on_writable (LacTLS *tls) -{ - -} - -static void -on_readable (LacTLS *tls) -{ - -} - -void -lac_tls_connect (LacTLS *tls) -{ - -} - -void -lac_tls_set_read_callback (LacTLS *tls, - LacWatchCallback read_cb) -{ -} - -void -lac_tls_set_write_callback (LacTLS *tls, - LacWatchCallback write_cb) -{ -} - -void -lac_tls_set_hangup_callback (LacTLS *tls, - LacWatchCallback hangup_cb) -{ -} - -void -lac_tls_set_error_callback (LacTLS *tls, - LacWatchCallback error_cb) -{ -} - -void -lac_tls_set_priority_callback (LacTLS *tls, - LacWatchCallback priority_cb) -{ -} - -int -lac_tls_send (LacTLS *tls, - char *msg, - guint len, - GError **err) -{ -} - -int -lac_tls_recv (LacTLS *tls, - char *buf, - guint size, - GError **err) -{ -} - -gboolean -lac_tls_free (LacTLS *tls, - GError **err) -{ -} - -#if 0 -LacTLS * lac_tls_new (GError *err); -gboolean lac_tls_connect (LacTLS *tls, - LacAddress *addr, - int port, - GError **err); -void lac_tls_set_read_callback (LacTLS *tls, - LacReadCallback cb, - gpointer data); -void lac_tls_set_write_callback (LacTLS *tls); -void lac_tls_set_hangup_callback (LacTLS *tls); -void lac_tls_send (LacTLS *tls); -void lac_tls_read (LacTLS *tls); - - -struct LacTLS -{ - int fd; - - /* tls */ - gnutls_anon_client_credentials_t anoncred; - gnutls_session_t session; -}; - - -static Socket * -socket_new_tcp (GError **err) -{ - Socket *socket; - int fd; - - fd = lac_socket_tcp (err); - - if (fd < 0) - return NULL; - - socket = g_new0 (Socket, 1); - socket->fd = fd; - - return socket; -} - -static Socket * -socket_new_ssl (GError **err) -{ - const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; - - fd = lac_socket_tcp (err); - if (fd < 0) - return NULL; - - socket = g_new0 (Socket, 1); - - socket->is_tls = TRUE; - - gnutls_global_init (); - gnutls_anon_allocate_client_credentials (&socket->anoncred); - gnutls_init (&socket->session, GNUTLS_CLIENT); - gnutls_set_default_priority (socket->session); - gnutls_kx_set_priority (socket->session, kx_prio); - gnutls_credentials_set (socket->session, - GNUTLS_CRD_ANON, &socket->anoncred); - - gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) socket->fd); -} - -static gboolean -socket_connect (Socket *socket, - LacAddress *address, - gint port, - GError **err) -{ - return lac_connect (socket->fd, address, port, err); -} - -static gboolean -socket_is_connected (Socket *socket, - GError **err) -{ - if (socket->is_tls) - { - /* We only get called when the fd is writable, which - * for TCP sockets means it's connected - */ - return TRUE; - } - else - { - int ret; - - do - { - ret = gnutls_handshake (socket->session); - } while (ret == GNUTLS_E_INTR); - - if (ret >= 0) - return TRUE; - - if (ret != GNUTLS_E_AGAIN) - { - /* FIXME: set error */ - g_warning ("err\n"); - } - - return FALSE; - } -} - -static gint -socket_send (Socket *socket, - const gchar *msg, - guint len, - GError **err) -{ - return lac_send (socket->fd, msg, len, err); -} - -static gint -socket_recv (Socket *socket, - gchar *buf, - guint size, - GError **err) -{ - return lac_recv (socket->fd, buf, size, err); -} - -static int -socket_get_fd (Socket *socket) -{ - return socket->fd; -} - -static gboolean -socket_close (Socket *socket, - GError **err) -{ - return lac_close (socket->fd, err); -} - -static void -socket_flush (Socket *socket) -{ - lac_set_nagle (socket->fd, FALSE, NULL); - lac_set_nagle (socket->fd, TRUE, NULL); -} - -static gboolean -socket_set_blocking (Socket *socket, - gboolean blocking, - GError **err) -{ - return lac_set_blocking (socket->fd, blocking, err); -} - -static gboolean -socket_shutdown (Socket *socket, - LacShutdownMethod how, - GError **err) -{ - return lac_shutdown (socket->fd, how, err); -} - - -#endif |