summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <sandmann@redhat.com>2007-07-30 03:13:13 -0400
committerSøren Sandmann <sandmann@redhat.com>2007-07-30 03:13:13 -0400
commitb97884394fd21858afbce6ef7f7e1720da1995b9 (patch)
treec7b9c9ccb83d0421ec3401c2fa9c3baeefd3f832
parentce041173ae98ce6c3b2e2f149d6974c4f0046277 (diff)
More TlsConnection
-rw-r--r--src/lac.h1
-rw-r--r--src/lacbytequeue.c6
-rw-r--r--src/lacconnection.c5
-rw-r--r--src/lactlsconnection.c151
4 files changed, 139 insertions, 24 deletions
diff --git a/src/lac.h b/src/lac.h
index 87f9e7c..e3650bc 100644
--- a/src/lac.h
+++ b/src/lac.h
@@ -190,6 +190,7 @@ LacByteQueue *lac_byte_queue_new (void);
gchar *lac_byte_queue_free (LacByteQueue *queue,
gboolean free_data);
gsize lac_byte_queue_get_length (LacByteQueue *queue);
+gboolean lac_byte_queue_is_empty (LacByteQueue *queue);
const gchar *lac_byte_queue_peek (LacByteQueue *queue,
gsize *n_bytes);
gchar *lac_byte_queue_steal (LacByteQueue *queue,
diff --git a/src/lacbytequeue.c b/src/lacbytequeue.c
index a2e37b6..075f157 100644
--- a/src/lacbytequeue.c
+++ b/src/lacbytequeue.c
@@ -82,8 +82,8 @@ lac_byte_queue_peek (LacByteQueue *queue,
}
}
-static gboolean
-is_empty (LacByteQueue *queue)
+gboolean
+lac_byte_queue_is_empty (LacByteQueue *queue)
{
return queue->start == queue->end;
}
@@ -249,7 +249,7 @@ void
lac_byte_queue_transfer_data (LacByteQueue *dest,
LacByteQueue *src)
{
- if (is_empty (dest))
+ if (lac_byte_queue_is_empty (dest))
{
if (dest->segment)
g_free (dest->segment);
diff --git a/src/lacconnection.c b/src/lacconnection.c
index d96a7f4..3913a5b 100644
--- a/src/lacconnection.c
+++ b/src/lacconnection.c
@@ -56,7 +56,12 @@ static void
event_free (LacConnectionEvent *event)
{
if (event->type == LAC_CONNECTION_EVENT_READ)
+ {
+ /* FIXME: at some point we should support pushing
+ * data back into the queue, ie., it must be kept alive
+ */
lac_byte_queue_free (event->read.byte_queue, TRUE);
+ }
else if (event->type == LAC_CONNECTION_EVENT_ERROR)
g_error_free ((GError *)event->error.err);
diff --git a/src/lactlsconnection.c b/src/lactlsconnection.c
index fb1f5a7..0be5d15 100644
--- a/src/lactlsconnection.c
+++ b/src/lactlsconnection.c
@@ -21,6 +21,8 @@
#include "lac.h"
#include <string.h>
+#include <gnutls/gnutls.h>
+#include <errno.h>
struct _LacTlsConnection
{
@@ -29,6 +31,10 @@ struct _LacTlsConnection
gpointer data;
LacByteQueue * buffer;
+
+ gnutls_anon_client_credentials_t anoncred;
+ gnutls_session_t session;
+
gboolean need_handshake;
};
@@ -52,40 +58,143 @@ tcp_callback (LacConnection *connection,
if (tls->need_handshake)
{
- /* if need handshake, attempt handshake */
- /* if successful
- * emit handshake
- * tls->need_handshake = FALSE
- */
+ if (gnutls_handshake (tls->session) == 0)
+ {
+ tls->need_handshake = FALSE;
+ /* FIXME: emit handshake event */
+ }
+ }
+
+ if (!tls->need_handshake)
+ {
+ LacByteQueue *queue;
+ gchar *buffer;
+ gssize n_read;
+ enum { BUF_SIZE = 8192 };
+ GError *err = NULL;
+
+ queue = lac_byte_queue_new ();
+
+ do
+ {
+ buffer = lac_byte_queue_alloc_tail (queue, BUF_SIZE);
+
+ n_read = gnutls_record_recv (tls->session, buffer, BUF_SIZE);
+
+ if (n_read < 0)
+ {
+ if (n_read != GNUTLS_E_INTERRUPTED &&
+ n_read != GNUTLS_E_AGAIN)
+ {
+ err = (GError *)0x01; /* FIXME */
+ }
+
+ n_read = 0;
+ }
+
+ lac_byte_queue_delete_tail (queue, BUF_SIZE - n_read);
+ }
+ while (n_read > 0);
+
+ if (!lac_byte_queue_is_empty (queue))
+ {
+ LacConnectionEvent read_event;
+ gsize n_bytes;
+
+ read_event.type = LAC_CONNECTION_EVENT_READ;
+ read_event.read.byte_queue = queue;
+ read_event.read.data = lac_byte_queue_peek (queue, &n_bytes);
+ read_event.read.len = n_bytes;
+
+ tls->callback (tls, &read_event);
+ }
+
+ if (err)
+ {
+ LacConnectionEvent error_event;
+
+ error_event.type = LAC_CONNECTION_EVENT_ERROR;
+ error_event.error.err = err;
+
+ tls->callback (tls, &error_event);
+
+ g_error_free (err);
+ lac_connection_close (tls->tcp_connection);
+ }
+
+ lac_byte_queue_free (queue, TRUE);
}
-
- /* attempt to read from the tls */
- /* if successful, emit read event */
- break;
-
- /* Connection closed */
- /* just re-emit */
break;
+ }
+}
- /* error */
- /* just re-emit */
- break;
+static ssize_t
+tls_push (gnutls_transport_ptr_t tptr,
+ const void *data,
+ size_t n_bytes)
+{
+ LacTlsConnection *tls = (LacTlsConnection *)tptr;
+
+ lac_connection_write (tls->tcp_connection, data, n_bytes);
+
+ return n_bytes;
+}
+
+static ssize_t
+tls_pull (gnutls_transport_ptr_t tptr,
+ void *data,
+ size_t n_bytes)
+{
+ LacTlsConnection *tls = (LacTlsConnection *)tptr;
+ const gchar *buf;
+ gsize n_available;
+
+ buf = lac_byte_queue_peek (tls->buffer, &n_available);
+
+ if (n_available > 0)
+ {
+ gsize minimum = n_bytes < n_available? n_bytes : n_available;
+
+ memcpy (data, buf, minimum);
+
+ errno = 0;
+
+ return minimum;
+ }
+ else
+ {
+ errno = EAGAIN;
+
+ return -1;
}
}
LacTlsConnection *
-lac_tls_connection_new (const LacAddress *address,
- gint port,
- LacTlsConnectionFunc callback,
- gpointer data)
+lac_tls_connection_new (const LacAddress *address,
+ gint port,
+ LacTlsConnectionFunc callback,
+ gpointer data)
{
LacTlsConnection *tls = g_new0 (LacTlsConnection, 1);
+ const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
- tls->tcp_connection = lac_connection_new (
- address, port, tcp_callback, tls);
+ tls->tcp_connection = lac_connection_new (address, port, tcp_callback, tls);
tls->need_handshake = TRUE;
tls->callback = callback;
tls->data = data;
+ gnutls_global_init ();
+ 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)tls);
+ gnutls_transport_set_push_function (tls->session, tls_push);
+ gnutls_transport_set_pull_function (tls->session, tls_pull);
+
+
return tls;
}