WIP commit for listener support.
authorLinus Nordberg <linus@nordberg.se>
Mon, 18 Feb 2013 16:12:20 +0000 (17:12 +0100)
committerLinus Nordberg <linus@nordberg.se>
Tue, 19 Feb 2013 10:07:00 +0000 (11:07 +0100)
20 files changed:
lib/Makefile.am
lib/compat.h
lib/conn.c
lib/conn.h
lib/err.c
lib/event.c
lib/examples/server.c
lib/include/radsec/radsec-impl.h
lib/include/radsec/radsec.h
lib/include/radsec/request-impl.h
lib/include/radsec/request.h
lib/message.c
lib/peer.c
lib/radsec.c
lib/radsec.sym
lib/request.c
lib/send.c
lib/tcp.c
lib/tls.c
lib/udp.c

index ebbe6cf..06ea8d5 100644 (file)
@@ -33,6 +33,7 @@ libradsec_la_SOURCES = \
        debug.c \
        err.c \
        event.c \
+       listener.c \
        message.c \
        peer.c \
        radsec.c \
index f132779..63de65f 100644 (file)
@@ -1,5 +1,11 @@
-/* Copyright 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
+#ifdef _WIN32
+#define INLINE __inline
+#else
+#define INLINE inline
+#endif
+
 ssize_t compat_send (int sockfd, const void *buf, size_t len, int flags);
 ssize_t compat_recv (int sockfd, void *buf, size_t len, int flags);
index 815784f..d8c1569 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
@@ -49,12 +49,12 @@ conn_activate_timeout (struct rs_connection *conn)
 {
   assert (conn);
   assert (conn->tev);
-  assert (conn->evb);
-  if (conn->timeout.tv_sec || conn->timeout.tv_usec)
+  assert (conn->base_.ctx->evb);
+  if (conn->base_.timeout.tv_sec || conn->base_.timeout.tv_usec)
     {
       rs_debug (("%s: activating timer: %d.%d\n", __func__,
                 conn->timeout.tv_sec, conn->timeout.tv_usec));
-      if (evtimer_add (conn->tev, &conn->timeout))
+      if (evtimer_add (conn->tev, &conn->base_.timeout))
        return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
                                    "evtimer_add: %d", errno);
     }
@@ -65,8 +65,8 @@ int
 conn_type_tls (const struct rs_connection *conn)
 {
   assert (conn->active_peer);
-  return conn->realm->type == RS_CONN_TYPE_TLS
-    || conn->realm->type == RS_CONN_TYPE_DTLS;
+  return conn->base_.realm->type == RS_CONN_TYPE_TLS
+    || conn->base_.realm->type == RS_CONN_TYPE_DTLS;
 }
 
 int
@@ -77,22 +77,35 @@ conn_cred_psk (const struct rs_connection *conn)
     conn->active_peer->transport_cred->type == RS_CRED_TLS_PSK;
 }
 
-
-/* Public functions. */
-int
-rs_conn_create (struct rs_context *ctx,
-               struct rs_connection **conn,
-               const char *config)
+void
+conn_init (struct rs_context *ctx,
+           struct rs_conn_base *connbase,
+           enum rs_conn_subtype type)
 {
-  struct rs_connection *c;
+  switch (type)
+    {
+    case RS_CONN_OBJTYPE_BASE:
+      connbase->magic = RS_CONN_MAGIC_BASE;
+      break;
+    case RS_CONN_OBJTYPE_GENERIC:
+      connbase->magic = RS_CONN_MAGIC_GENERIC;
+      break;
+    case RS_CONN_OBJTYPE_LISTENER:
+      connbase->magic = RS_CONN_MAGIC_LISTENER;
+      break;
+    default:
+      assert ("invalid connection subtype" == NULL);
+    }
 
-  c = (struct rs_connection *) malloc (sizeof(struct rs_connection));
-  if (!c)
-    return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL);
+  connbase->ctx = ctx;
+  connbase->fd = -1;
+}
 
-  memset (c, 0, sizeof(struct rs_connection));
-  c->ctx = ctx;
-  c->fd = -1;
+int
+conn_configure (struct rs_context *ctx,
+                struct rs_conn_base *connbase,
+                const char *config)
+{
   if (config)
     {
       struct rs_realm *r = rs_conf_find_realm (ctx, config);
@@ -100,34 +113,59 @@ rs_conn_create (struct rs_context *ctx,
        {
          struct rs_peer *p;
 
-         c->realm = r;
-         c->peers = r->peers;  /* FIXME: Copy instead?  */
-         for (p = c->peers; p != NULL; p = p->next)
-           p->conn = c;
-         c->timeout.tv_sec = r->timeout;
-         c->tryagain = r->retries;
+         connbase->realm = r;
+         connbase->peers = r->peers; /* FIXME: Copy instead?  */
+         for (p = connbase->peers; p != NULL; p = p->next)
+           p->conn = TO_GENERIC_CONN(connbase);
+         connbase->timeout.tv_sec = r->timeout;
+         connbase->tryagain = r->retries;
        }
       else
        {
-         c->realm = rs_malloc (ctx, sizeof (struct rs_realm));
-         if (!c->realm)
+         connbase->realm = rs_malloc (ctx, sizeof (struct rs_realm));
+         if (!connbase->realm)
            return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__,
                                       NULL);
-         memset (c->realm, 0, sizeof (struct rs_realm));
+         memset (connbase->realm, 0, sizeof (struct rs_realm));
        }
     }
+  return RSE_OK;
+}
+
+/* Public functions. */
+int
+rs_conn_create (struct rs_context *ctx,
+               struct rs_connection **conn,
+               const char *config)
+{
+  int err = RSE_OK;
+  struct rs_connection *c = NULL;
+  assert (ctx);
+
+  c = rs_calloc (ctx, 1, sizeof (struct rs_connection));
+  if (c == NULL)
+    return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL);
+  conn_init (ctx, &c->base_, RS_CONN_OBJTYPE_GENERIC);
+  err = conn_configure (ctx, &c->base_, config);
+  if (err)
+    goto errout;
 
   if (conn)
     *conn = c;
   return RSE_OK;
+
+ errout:
+  if (c)
+    rs_free (ctx, c);
+  return err;
 }
 
 void
 rs_conn_set_type (struct rs_connection *conn, rs_conn_type_t type)
 {
   assert (conn);
-  assert (conn->realm);
-  conn->realm->type = type;
+  assert (conn->base_.realm);
+  conn->base_.realm->type = type;
 }
 
 int
@@ -147,8 +185,8 @@ rs_conn_disconnect (struct rs_connection *conn)
 
   assert (conn);
 
-  err = evutil_closesocket (conn->fd);
-  conn->fd = -1;
+  err = evutil_closesocket (conn->base_.fd);
+  conn->base_.fd = -1;
   return err;
 }
 
@@ -174,16 +212,14 @@ rs_conn_destroy (struct rs_connection *conn)
 
   if (conn->tev)
     event_free (conn->tev);
-  if (conn->bev)
-    bufferevent_free (conn->bev);
-  if (conn->rev)
-    event_free (conn->rev);
-  if (conn->wev)
-    event_free (conn->wev);
-  if (conn->evb)
-    event_base_free (conn->evb);
+  if (conn->base_.bev)
+    bufferevent_free (conn->base_.bev);
+  if (conn->base_.rev)
+    event_free (conn->base_.rev);
+  if (conn->base_.wev)
+    event_free (conn->base_.wev);
 
-  rs_free (conn->ctx, conn);
+  rs_free (conn->base_.ctx, conn);
 
   return err;
 }
@@ -230,15 +266,15 @@ rs_conn_get_current_peer (struct rs_connection *conn,
 }
 
 int
-rs_conn_dispatch(struct rs_connection *conn)
+rs_conn_dispatch (struct rs_connection *conn)
 {
   assert (conn);
-  return event_base_loop (conn->evb, EVLOOP_ONCE);
+  return event_base_loop (conn->base_.ctx->evb, EVLOOP_ONCE);
 }
 
 #if 0
 struct event_base
-*rs_conn_get_evb(const struct rs_connection *conn)
+*rs_conn_get_evb (const struct rs_connection *conn)
 {
   assert (conn);
   return conn->evb;
@@ -249,7 +285,7 @@ int rs_conn_get_fd (struct rs_connection *conn)
 {
   assert (conn);
   assert (conn->active_peer);
-  return conn->fd;
+  return conn->base_.fd;
 }
 
 static void
@@ -260,10 +296,10 @@ _rcb (struct rs_message *message, void *user_data)
   assert (msg->conn);
 
   msg->flags |= RS_MESSAGE_RECEIVED;
-  if (msg->conn->bev)
-    bufferevent_disable (msg->conn->bev, EV_WRITE|EV_READ);
+  if (msg->conn->base_.bev)
+    bufferevent_disable (msg->conn->base_.bev, EV_WRITE|EV_READ);
   else
-    event_del (msg->conn->rev);
+    event_del (msg->conn->base_.rev);
 }
 
 int
@@ -275,32 +311,33 @@ rs_conn_receive_message (struct rs_connection *conn,
   struct rs_message *msg = NULL;
 
   assert (conn);
-  assert (conn->realm);
+  assert (conn->base_.realm);
   assert (!conn_user_dispatch_p (conn)); /* Blocking mode only.  */
 
   if (rs_message_create (conn, &msg))
     return -1;
 
-  assert (conn->evb);
-  assert (conn->fd >= 0);
+  assert (conn->base_.ctx->evb);
+  assert (conn->base_.fd >= 0);
 
   conn->callbacks.received_cb = _rcb;
-  conn->user_data = msg;
+  conn->base_.user_data = msg;
   msg->flags &= ~RS_MESSAGE_RECEIVED;
 
-  if (conn->bev)               /* TCP.  */
+  if (conn->base_.bev)         /* TCP.  */
     {
-      bufferevent_setwatermark (conn->bev, EV_READ, RS_HEADER_LEN, 0);
-      bufferevent_setcb (conn->bev, tcp_read_cb, NULL, tcp_event_cb, msg);
-      bufferevent_enable (conn->bev, EV_READ);
+      bufferevent_setwatermark (conn->base_.bev, EV_READ, RS_HEADER_LEN, 0);
+      bufferevent_setcb (conn->base_.bev, tcp_read_cb, NULL, tcp_event_cb, msg);
+      bufferevent_enable (conn->base_.bev, EV_READ);
     }
   else                         /* UDP.  */
     {
       /* Put fresh message in user_data for the callback and enable the
         read event.  */
-      event_assign (conn->rev, conn->evb, event_get_fd (conn->rev),
-                   EV_READ, event_get_callback (conn->rev), msg);
-      err = event_add (conn->rev, NULL);
+      event_assign (conn->base_.rev, conn->base_.ctx->evb,
+                    event_get_fd (conn->base_.rev), EV_READ,
+                    event_get_callback (conn->base_.rev), msg);
+      err = event_add (conn->base_.rev, NULL);
       if (err < 0)
        return rs_err_conn_push_fl (msg->conn, RSE_EVENT, __FILE__, __LINE__,
                                    "event_add: %s",
@@ -311,7 +348,7 @@ rs_conn_receive_message (struct rs_connection *conn,
     }
 
   rs_debug (("%s: entering event loop\n", __func__));
-  err = event_base_dispatch (conn->evb);
+  err = event_base_dispatch (conn->base_.ctx->evb);
   conn->callbacks.received_cb = NULL;
   if (err < 0)
     return rs_err_conn_push_fl (msg->conn, RSE_EVENT, __FILE__, __LINE__,
@@ -340,5 +377,5 @@ rs_conn_set_timeout(struct rs_connection *conn, struct timeval *tv)
 {
   assert (conn);
   assert (tv);
-  conn->timeout = *tv;
+  conn->base_.timeout = *tv;
 }
index c538a8c..c1543d9 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 int conn_close (struct rs_connection **connp);
@@ -6,3 +6,9 @@ int conn_user_dispatch_p (const struct rs_connection *conn);
 int conn_activate_timeout (struct rs_connection *conn);
 int conn_type_tls (const struct rs_connection *conn);
 int conn_cred_psk (const struct rs_connection *conn);
+int conn_configure (struct rs_context *ctx,
+                    struct rs_conn_base *connbase,
+                    const char *config);
+void conn_init (struct rs_context *ctx,
+                struct rs_conn_base *connbase,
+                enum rs_conn_subtype type);
index 19e1f33..e0bcea9 100644 (file)
--- a/lib/err.c
+++ b/lib/err.c
@@ -1,4 +1,4 @@
-/* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
@@ -159,9 +159,9 @@ int
 err_conn_push_err (struct rs_connection *conn, struct rs_error *err)
 {
 
-  if (conn->err)
-    rs_err_free (conn->err);
-  conn->err = err;             /* FIXME: use a stack */
+  if (conn->base_.err)
+    rs_err_free (conn->base_.err);
+  conn->base_.err = err;               /* FIXME: use a stack */
 
   return err->code;
 }
@@ -225,8 +225,8 @@ rs_err_conn_pop (struct rs_connection *conn)
 
   if (!conn)
     return NULL;               /* FIXME: RSE_INVALID_CONN */
-  err = conn->err;
-  conn->err = NULL;
+  err = conn->base_.err;
+  conn->base_.err = NULL;
 
   return err;
 }
@@ -236,8 +236,8 @@ rs_err_conn_peek_code (struct rs_connection *conn)
 {
   if (!conn)
     return -1;                 /* FIXME: RSE_INVALID_CONN */
-  if (conn->err)
-    return conn->err->code;
+  if (conn->base_.err)
+    return conn->base_.err->code;
 
   return RSE_OK;
 }
index ff64348..f7b936a 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
@@ -99,7 +99,7 @@ event_retransmit_timeout_cb (int fd, short event, void *data)
 int
 event_init_socket (struct rs_connection *conn, struct rs_peer *p)
 {
-  if (conn->fd != -1)
+  if (conn->base_.fd != -1)
     return RSE_OK;
 
   if (p->addr_cache == NULL)
@@ -110,16 +110,16 @@ event_init_socket (struct rs_connection *conn, struct rs_peer *p)
         return err_conn_push_err (conn, err);
     }
 
-  conn->fd = socket (p->addr_cache->ai_family, p->addr_cache->ai_socktype,
+  conn->base_.fd = socket (p->addr_cache->ai_family, p->addr_cache->ai_socktype,
                     p->addr_cache->ai_protocol);
-  if (conn->fd < 0)
+  if (conn->base_.fd < 0)
     return rs_err_conn_push_fl (conn, RSE_SOCKERR, __FILE__, __LINE__,
                                "socket: %d (%s)",
                                errno, strerror (errno));
-  if (evutil_make_socket_nonblocking (conn->fd) < 0)
+  if (evutil_make_socket_nonblocking (conn->base_.fd) < 0)
     {
-      evutil_closesocket (conn->fd);
-      conn->fd = -1;
+      evutil_closesocket (conn->base_.fd);
+      conn->base_.fd = -1;
       return rs_err_conn_push_fl (conn, RSE_SOCKERR, __FILE__, __LINE__,
                                  "evutil_make_socket_nonblocking: %d (%s)",
                                  errno, strerror (errno));
@@ -130,28 +130,30 @@ event_init_socket (struct rs_connection *conn, struct rs_peer *p)
 int
 event_init_bufferevent (struct rs_connection *conn, struct rs_peer *peer)
 {
-  if (conn->bev)
+  if (conn->base_.bev)
     return RSE_OK;
 
-  if (conn->realm->type == RS_CONN_TYPE_TCP)
+  if (conn->base_.realm->type == RS_CONN_TYPE_TCP)
     {
-      conn->bev = bufferevent_socket_new (conn->evb, conn->fd, 0);
-      if (!conn->bev)
+      conn->base_.bev = bufferevent_socket_new (conn->base_.ctx->evb,
+                                              conn->base_.fd, 0);
+      if (!conn->base_.bev)
        return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
                                    "bufferevent_socket_new");
     }
 #if defined (RS_ENABLE_TLS)
-  else if (conn->realm->type == RS_CONN_TYPE_TLS)
+  else if (conn->base_.realm->type == RS_CONN_TYPE_TLS)
     {
       if (rs_tls_init (conn))
        return -1;
       /* Would be convenient to pass BEV_OPT_CLOSE_ON_FREE but things
         seem to break when be_openssl_ctrl() (in libevent) calls
         SSL_set_bio() after BIO_new_socket() with flag=1.  */
-      conn->bev =
-       bufferevent_openssl_socket_new (conn->evb, conn->fd, conn->tls_ssl,
+      conn->base_.bev =
+       bufferevent_openssl_socket_new (conn->base_.ctx->evb, conn->base_.fd,
+                                        conn->tls_ssl,
                                        BUFFEREVENT_SSL_CONNECTING, 0);
-      if (!conn->bev)
+      if (!conn->base_.bev)
        return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
                                    "bufferevent_openssl_socket_new");
     }
@@ -160,7 +162,7 @@ event_init_bufferevent (struct rs_connection *conn, struct rs_peer *peer)
     {
       return rs_err_conn_push_fl (conn, RSE_INTERNAL, __FILE__, __LINE__,
                                  "%s: unknown connection type: %d", __func__,
-                                 conn->realm->type);
+                                 conn->base_.realm->type);
     }
 
   return RSE_OK;
@@ -188,10 +190,11 @@ event_do_connect (struct rs_connection *conn)
   }
 #endif
 
-  if (p->conn->bev)            /* TCP */
+  if (p->conn->base_.bev)              /* TCP */
     {
       conn_activate_timeout (conn); /* Connect timeout.  */
-      err = bufferevent_socket_connect (p->conn->bev, p->addr_cache->ai_addr,
+      err = bufferevent_socket_connect (p->conn->base_.bev,
+                                        p->addr_cache->ai_addr,
                                        p->addr_cache->ai_addrlen);
       if (err < 0)
        rs_err_conn_push_fl (p->conn, RSE_EVENT, __FILE__, __LINE__,
@@ -202,7 +205,7 @@ event_do_connect (struct rs_connection *conn)
     }
   else                         /* UDP */
     {
-      err = connect (p->conn->fd,
+      err = connect (p->conn->base_.fd,
                      p->addr_cache->ai_addr,
                      p->addr_cache->ai_addrlen);
       if (err < 0)
@@ -211,7 +214,7 @@ event_do_connect (struct rs_connection *conn)
          rs_debug (("%s: %d: connect: %d (%s)\n", __func__, p->conn->fd,
                     sockerr, evutil_socket_error_to_string (sockerr)));
          rs_err_conn_push_fl (p->conn, RSE_SOCKERR, __FILE__, __LINE__,
-                              "%d: connect: %d (%s)", p->conn->fd, sockerr,
+                              "%d: connect: %d (%s)", p->conn->base_.fd, sockerr,
                               evutil_socket_error_to_string (sockerr));
        }
     }
@@ -220,7 +223,7 @@ event_do_connect (struct rs_connection *conn)
 int
 event_loopbreak (struct rs_connection *conn)
 {
-  int err = event_base_loopbreak (conn->evb);
+  int err = event_base_loopbreak (conn->base_.ctx->evb);
   if (err < 0)
     rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
                         "event_base_loopbreak: %s",
@@ -236,7 +239,7 @@ event_on_disconnect (struct rs_connection *conn)
   conn->is_connected = 0;
   rs_debug (("%s: %p disconnected\n", __func__, conn->active_peer));
   if (conn->callbacks.disconnected_cb)
-    conn->callbacks.disconnected_cb (conn->user_data);
+    conn->callbacks.disconnected_cb (conn->base_.user_data);
 }
 
 /** Internal connect event returning 0 on success or -1 on error.  */
@@ -259,7 +262,7 @@ event_on_connect (struct rs_connection *conn, struct rs_message *msg)
   rs_debug (("%s: %p connected\n", __func__, conn->active_peer));
 
   if (conn->callbacks.connected_cb)
-    conn->callbacks.connected_cb (conn->user_data);
+    conn->callbacks.connected_cb (conn->base_.user_data);
 
   if (msg)
     message_do_send (msg);
@@ -271,7 +274,8 @@ int
 event_init_eventbase (struct rs_connection *conn)
 {
   assert (conn);
-  if (conn->evb)
+  assert (conn->base_.ctx);
+  if (conn->base_.ctx->evb)
     return RSE_OK;
 
 #if defined (DEBUG)
@@ -279,8 +283,8 @@ event_init_eventbase (struct rs_connection *conn)
     event_enable_debug_mode ();
 #endif
   event_set_log_callback (_evlog_cb);
-  conn->evb = event_base_new ();
-  if (!conn->evb)
+  conn->base_.ctx->evb = event_base_new ();
+  if (!conn->base_.ctx->evb)
     return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
                                "event_base_new");
 
index 88c2bf4..8c304a0 100644 (file)
@@ -1,5 +1,8 @@
 /* RADIUS/RadSec server using libradsec. */
 
+/* Copyright 2013 NORDUnet A/S. All rights reserved.
+   See LICENSE for licensing information.  */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <assert.h>
 #define USER_NAME "molgan@PROJECT-MOONSHOT.ORG"
 #define USER_PW "password"
 
+void
+new_conn_cb (struct rs_connection *conn, void *user_data)
+{
+  printf ("new connection: fd=%d\n", -1); /* conn->fd */
+}
 
 struct rs_error *
 server (struct rs_context *ctx)
 {
+  int r = 0;
   struct rs_error *err = NULL;
   struct rs_connection *conn = NULL;
-#if 0
   struct rs_listener *listener = NULL;
+  const struct rs_listener_callbacks cbs = {};
 
   if (rs_listener_create (ctx, &listener, CONFIG))
     goto out;
+  rs_listener_set_callbacks (listener, &cbs);
 
-  while (1)
+  do
     {
-      if (rs_listener_dispatch (listener))
-        goto out;
+      r = rs_listener_dispatch (listener);
+      printf ("DEBUG: rs_listener_dispatch done (r=%d)\n", r);
     }
+  while (r == 0);
 
  out:
-#endif
-
   err = rs_err_ctx_pop (ctx);
   if (err == NULL)
     err = rs_err_conn_pop (conn);
index 32753ef..fecf8f2 100644 (file)
@@ -1,17 +1,19 @@
 /** @file libradsec-impl.h
     @brief Libraray internal header file for libradsec.  */
 
-/* Copyright 2010, 2011, 2013 NORDUnet A/S. All rights reserved.
+/* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information. */
 
 #ifndef _RADSEC_RADSEC_IMPL_H_
 #define _RADSEC_RADSEC_IMPL_H_ 1
 
+#include <assert.h>
 #include <event2/util.h>
 #include <confuse.h>
 #if defined(RS_ENABLE_TLS)
 #include <openssl/ssl.h>
 #endif
+#include "compat.h"
 
 /* Constants.  */
 #define RS_HEADER_LEN 4
@@ -86,33 +88,49 @@ struct rs_config {
     cfg_t *cfg;
 };
 
+/** Libradsec context. */
 struct rs_context {
     struct rs_config *config;
     struct rs_alloc_scheme alloc_scheme;
     struct rs_error *err;
+    struct event_base *evb;    /* Event base.  */
 };
 
-struct rs_connection {
+enum rs_conn_subtype {
+    RS_CONN_OBJTYPE_BASE = 1,
+    RS_CONN_OBJTYPE_GENERIC,
+    RS_CONN_OBJTYPE_LISTENER,
+};
+#define RS_CONN_MAGIC_BASE 0xAE004711u
+#define RS_CONN_MAGIC_GENERIC 0x843AEF47u
+#define RS_CONN_MAGIC_LISTENER 0xDCB04783u
+
+/** Base class for a connection. */
+struct rs_conn_base {
+    uint32_t magic;             /* Must be one of RS_CONN_MAGIC_*. */
     struct rs_context *ctx;
     struct rs_realm *realm;    /* Owned by ctx.  */
-    struct event_base *evb;    /* Event base.  */
-    struct event *tev;         /* Timeout event.  */
-    struct rs_conn_callbacks callbacks;
+    struct rs_peer *peers;      /*< Configured peers. */
+    struct timeval timeout;
+    int tryagain;              /* For server failover.  */
     void *user_data;
-    struct rs_peer *peers;
-    struct rs_peer *active_peer;
     struct rs_error *err;
-    struct timeval timeout;
-    char is_connecting;                /* FIXME: replace with a single state member */
-    char is_connected;         /* FIXME: replace with a single state member */
     int fd;                    /* Socket.  */
-    int tryagain;              /* For server failover.  */
-    int nextid;                        /* Next RADIUS packet identifier.  */
     /* TCP transport specifics.  */
     struct bufferevent *bev;   /* Buffer event.  */
     /* UDP transport specifics.  */
     struct event *wev;         /* Write event (for UDP).  */
     struct event *rev;         /* Read event (for UDP).  */
+};
+
+/** A "generic" connection. */
+struct rs_connection {
+    struct rs_conn_base base_;
+    struct event *tev;         /* Timeout event.  */
+    struct rs_conn_callbacks callbacks;
+    struct rs_peer *active_peer;
+    char is_connecting;                /* FIXME: replace with a single state member */
+    char is_connected;         /* FIXME: replace with a single state member */
     struct rs_message *out_queue; /* Queue for outgoing UDP packets.  */
 #if defined(RS_ENABLE_TLS)
     /* TLS specifics.  */
@@ -121,6 +139,14 @@ struct rs_connection {
 #endif
 };
 
+/** A listening connection. Spawns generic connections when peers
+ * connect to it. */
+struct rs_listener {
+    struct rs_conn_base base_;
+    struct evconnlistener *evlistener;
+    struct rs_listener_callbacks callbacks;
+};
+
 enum rs_message_flags {
     RS_MESSAGE_HEADER_READ,
     RS_MESSAGE_RECEIVED,
@@ -141,7 +167,10 @@ struct rs_message {
 }
 #endif
 
+/************************/
 /* Convenience macros.  */
+
+/* Memory allocation. */
 #define rs_calloc(h, nmemb, size) ((h)->alloc_scheme.calloc != NULL \
      ? (h)->alloc_scheme.calloc : calloc)((nmemb), (size))
 #define rs_malloc(h, size) ((h)->alloc_scheme.malloc != NULL \
@@ -153,6 +182,29 @@ struct rs_message {
 #define min(a, b) ((a) < (b) ? (a) : (b))
 #define max(a, b) ((a) > (b) ? (a) : (b))
 
+/* Basic CPP-based classes, proudly borrowed from Tor. */
+#if defined(__GNUC__) && __GNUC__ > 3
+ #define STRUCT_OFFSET(tp, member) __builtin_offsetof(tp, member)
+#else
+ #define STRUCT_OFFSET(tp, member) \
+   ((off_t) (((char*)&((tp*)0)->member)-(char*)0))
+#endif
+#define SUBTYPE_P(p, subtype, basemember) \
+  ((void*) (((char*)(p)) - STRUCT_OFFSET(subtype, basemember)))
+#define DOWNCAST(to, ptr) ((to*)SUBTYPE_P(ptr, to, base_))
+static struct rs_connection *TO_GENERIC_CONN (struct rs_conn_base *);
+static struct rs_listener *TO_LISTENER_CONN (struct rs_conn_base *);
+static INLINE struct rs_connection *TO_GENERIC_CONN (struct rs_conn_base *b)
+{
+  assert (b->magic == RS_CONN_MAGIC_GENERIC);
+  return DOWNCAST (struct rs_connection, b);
+}
+static INLINE struct rs_listener *TO_LISTENER_CONN (struct rs_conn_base *b)
+{
+  assert (b->magic == RS_CONN_MAGIC_LISTENER);
+  return DOWNCAST (struct rs_listener, b);
+}
+
 #endif /* _RADSEC_RADSEC_IMPL_H_ */
 
 /* Local Variables: */
index 0a43f6f..021f677 100644 (file)
@@ -1,7 +1,8 @@
 /** \file radsec.h
     \brief Public interface for libradsec.  */
 
-/* See LICENSE for licensing information.  */
+/* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
+   See LICENSE for licensing information. */
 
 #ifndef _RADSEC_RADSEC_H_
 #define _RADSEC_RADSEC_H_ 1
@@ -136,6 +137,7 @@ extern "C" {
 /* Data types.  */
 struct rs_context;             /* radsec-impl.h */
 struct rs_connection;          /* radsec-impl.h */
+struct rs_listener;             /* radsec-impl.h */
 struct rs_message;             /* radsec-impl.h */
 struct rs_conn;                        /* radsec-impl.h */
 struct rs_error;               /* radsec-impl.h */
@@ -161,7 +163,7 @@ typedef void (*rs_conn_message_received_cb) (struct rs_message *message,
                                              void *user_data);
 typedef void (*rs_conn_message_sent_cb) (void *user_data);
 struct rs_conn_callbacks {
-    /** Callback invoked when the connection has been established.  */
+    /** Callback invoked when an outgoing connection has been established.  */
     rs_conn_connected_cb connected_cb;
     /** Callback invoked when the connection has been torn down.  */
     rs_conn_disconnected_cb disconnected_cb;
@@ -171,6 +173,12 @@ struct rs_conn_callbacks {
     rs_conn_message_sent_cb sent_cb;
 };
 
+typedef void (*rs_listener_new_conn_cb) (struct rs_connection *conn,
+                                         void *user_data);
+struct rs_listener_callbacks {
+    rs_listener_new_conn_cb new_conn_cb;
+};
+
 typedef struct value_pair rs_avp;
 typedef const struct value_pair rs_const_avp;
 
@@ -210,6 +218,15 @@ int rs_context_read_config(struct rs_context *ctx, const char *config_file);
 
 int rs_context_print_config (struct rs_context *ctx, char **buf_out);
 
+/*************/
+/* Listener. */
+/*************/
+int rs_listener_create (struct rs_context *ctx,
+                        struct rs_listener **listener,
+                        const char *config);
+void rs_listener_set_callbacks (struct rs_listener *listener,
+                                const struct rs_listener_callbacks *cb);
+int rs_listener_dispatch (const struct rs_listener *listener);
 
 /****************/
 /* Connection.  */
@@ -319,7 +336,7 @@ void rs_peer_set_timeout(struct rs_peer *peer, int timeout);
 void rs_peer_set_retries(struct rs_peer *peer, int retries);
 
 /************/
-/* Message.  */
+/* Message. */
 /************/
 /** Create a message associated with connection \a conn.  */
 int rs_message_create(struct rs_connection *conn, struct rs_message **pkt_out);
index 9af1394..dbb4244 100644 (file)
@@ -1,4 +1,5 @@
-/* See LICENSE for licensing information.  */
+/* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
+   See LICENSE for licensing information. */
 
 #ifndef _RADSEC_REQUEST_IMPL_H_
 #define _RADSEC_REQUEST_IMPL_H_ 1
index 05b5daa..b78411a 100644 (file)
@@ -1,7 +1,8 @@
 /** \file request.h
     \brief Public interface for libradsec request's.  */
 
-/* See LICENSE for licensing information.  */
+/* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
+   See LICENSE for licensing information. */
 
 #ifndef _RADSEC_REQUEST_H_
 #define _RADSEC_REQUEST_H_ 1
index 7ded6e7..e010f94 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
@@ -102,9 +102,9 @@ message_do_send (struct rs_message *msg)
 #endif
 
   /* Put message in output buffer.  */
-  if (msg->conn->bev)          /* TCP.  */
+  if (msg->conn->base_.bev)       /* TCP.  */
     {
-      int err = bufferevent_write (msg->conn->bev, msg->rpkt->data,
+      int err = bufferevent_write (msg->conn->base_.bev, msg->rpkt->data,
                                   msg->rpkt->length);
       if (err < 0)
        return rs_err_conn_push_fl (msg->conn, RSE_EVENT, __FILE__, __LINE__,
@@ -133,7 +133,7 @@ rs_message_create (struct rs_connection *conn, struct rs_message **msg_out)
 
   *msg_out = NULL;
 
-  rpkt = rs_malloc (conn->ctx, sizeof(*rpkt) + RS_MAX_PACKET_LEN);
+  rpkt = rs_malloc (conn->base_.ctx, sizeof(*rpkt) + RS_MAX_PACKET_LEN);
   if (rpkt == NULL)
     return rs_err_conn_push (conn, RSE_NOMEM, __func__);
 
@@ -143,10 +143,10 @@ rs_message_create (struct rs_connection *conn, struct rs_message **msg_out)
   if (err < 0)
     return rs_err_conn_push (conn, -err, __func__);
 
-  p = (struct rs_message *) rs_calloc (conn->ctx, 1, sizeof (*p));
+  p = (struct rs_message *) rs_calloc (conn->base_.ctx, 1, sizeof (*p));
   if (p == NULL)
     {
-      rs_free (conn->ctx, rpkt);
+      rs_free (conn->base_.ctx, rpkt);
       return rs_err_conn_push (conn, RSE_NOMEM, __func__);
     }
   p->conn = conn;
@@ -195,11 +195,11 @@ rs_message_destroy (struct rs_message *msg)
 {
   assert (msg);
   assert (msg->conn);
-  assert (msg->conn->ctx);
+  assert (msg->conn->base_.ctx);
 
   rs_avp_free (&msg->rpkt->vps);
-  rs_free (msg->conn->ctx, msg->rpkt);
-  rs_free (msg->conn->ctx, msg);
+  rs_free (msg->conn->base_.ctx, msg->rpkt);
+  rs_free (msg->conn->base_.ctx, msg);
 }
 
 int
index 0ac4114..3e0069b 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
@@ -23,7 +23,7 @@ peer_pick_peer (struct rs_connection *conn)
   if (conn->active_peer)
     conn->active_peer = conn->active_peer->next; /* Next.  */
   if (!conn->active_peer)
-    conn->active_peer = conn->peers; /* From the top.  */
+    conn->active_peer = conn->base_.peers; /* From the top.  */
 
   return conn->active_peer;
 }
@@ -54,7 +54,7 @@ rs_peer_create (struct rs_connection *conn, struct rs_peer **peer_out)
 {
   struct rs_peer *peer;
 
-  peer = peer_create (conn->ctx, &conn->peers);
+  peer = peer_create (conn->base_.ctx, &conn->base_.peers);
   if (peer)
     {
       peer->conn = conn;
@@ -74,10 +74,10 @@ rs_peer_set_address (struct rs_peer *peer, const char *hostname,
 {
   assert (peer);
   assert (peer->conn);
-  assert (peer->conn->ctx);
+  assert (peer->conn->base_.ctx);
 
-  peer->hostname = rs_strdup (peer->conn->ctx, hostname);
-  peer->service = rs_strdup (peer->conn->ctx, service);
+  peer->hostname = rs_strdup (peer->conn->base_.ctx, hostname);
+  peer->service = rs_strdup (peer->conn->base_.ctx, service);
   if (peer->hostname == NULL || peer->service == NULL)
     return RSE_NOMEM;
 
index e6b79cf..48fe221 100644 (file)
@@ -127,6 +127,9 @@ rs_context_destroy (struct rs_context *ctx)
       rs_free (ctx, ctx->config);
     }
 
+  if (ctx->evb)
+    event_base_free (ctx->evb);
+
   free (ctx);
 }
 
index 6378cfd..7e64560 100644 (file)
@@ -67,6 +67,9 @@ rs_err_ctx_push
 rs_err_ctx_push_fl
 rs_err_free
 rs_err_msg
+rs_listener_create
+rs_listener_dispatch
+rs_listener_set_callbacks
 rs_message_append_avp
 rs_message_avps
 rs_message_code
index 8f3635d..17b36de 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
@@ -30,7 +30,7 @@
 int
 rs_request_create (struct rs_connection *conn, struct rs_request **req_out)
 {
-  struct rs_request *req = rs_malloc (conn->ctx, sizeof(*req));
+  struct rs_request *req = rs_malloc (conn->base_.ctx, sizeof(*req));
   assert (req_out);
   if (!req)
     return rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
@@ -73,11 +73,11 @@ rs_request_destroy (struct rs_request *request)
 {
   assert (request);
   assert (request->conn);
-  assert (request->conn->ctx);
+  assert (request->conn->base_.ctx);
 
   if (request->req_msg)
     rs_message_destroy (request->req_msg);
-  rs_free (request->conn->ctx, request);
+  rs_free (request->conn->base_.ctx, request);
 }
 
 static void
index 1234fdd..6b76958 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
@@ -32,8 +32,8 @@ _conn_open (struct rs_connection *conn, struct rs_message *msg)
   if (event_init_socket (conn, conn->active_peer))
     return -1;
 
-  if (conn->realm->type == RS_CONN_TYPE_TCP
-      || conn->realm->type == RS_CONN_TYPE_TLS)
+  if (conn->base_.realm->type == RS_CONN_TYPE_TCP
+      || conn->base_.realm->type == RS_CONN_TYPE_TLS)
     {
       if (tcp_init_connect_timer (conn))
        return -1;
@@ -68,10 +68,10 @@ _wcb (void *user_data)
   struct rs_message *msg = (struct rs_message *) user_data;
   assert (msg);
   msg->flags |= RS_MESSAGE_SENT;
-  if (msg->conn->bev)
-    bufferevent_disable (msg->conn->bev, EV_WRITE|EV_READ);
+  if (msg->conn->base_.bev)
+    bufferevent_disable (msg->conn->base_.bev, EV_WRITE|EV_READ);
   else
-    event_del (msg->conn->wev);
+    event_del (msg->conn->base_.wev);
 }
 
 int
@@ -90,22 +90,24 @@ rs_message_send (struct rs_message *msg, void *user_data)
     if (_conn_open (conn, msg))
       return -1;
 
-  assert (conn->evb);
+  assert (conn->base_.ctx);
+  assert (conn->base_.ctx->evb);
   assert (conn->active_peer);
-  assert (conn->fd >= 0);
+  assert (conn->base_.fd >= 0);
 
-  conn->user_data = user_data;
+  conn->base_.user_data = user_data;
 
-  if (conn->bev)               /* TCP */
+  if (conn->base_.bev)         /* TCP */
     {
-      bufferevent_setcb (conn->bev, NULL, tcp_write_cb, tcp_event_cb, msg);
-      bufferevent_enable (conn->bev, EV_WRITE);
+      bufferevent_setcb (conn->base_.bev, NULL, tcp_write_cb, tcp_event_cb, msg);
+      bufferevent_enable (conn->base_.bev, EV_WRITE);
     }
   else                         /* UDP */
     {
-      event_assign (conn->wev, conn->evb, event_get_fd (conn->wev),
-                   EV_WRITE, event_get_callback (conn->wev), msg);
-      err = event_add (conn->wev, NULL);
+      event_assign (conn->base_.wev, conn->base_.ctx->evb,
+                    event_get_fd (conn->base_.wev),
+                   EV_WRITE, event_get_callback (conn->base_.wev), msg);
+      err = event_add (conn->base_.wev, NULL);
       if (err < 0)
        return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
                                    "event_add: %s",
@@ -116,16 +118,16 @@ rs_message_send (struct rs_message *msg, void *user_data)
   if (!conn_user_dispatch_p (conn))
     {
       conn->callbacks.sent_cb = _wcb;
-      conn->user_data = msg;
+      conn->base_.user_data = msg;
       rs_debug (("%s: entering event loop\n", __func__));
-      err = event_base_dispatch (conn->evb);
+      err = event_base_dispatch (conn->base_.ctx->evb);
       if (err < 0)
        return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
                                    "event_base_dispatch: %s",
                                    evutil_gai_strerror (err));
       rs_debug (("%s: event loop done\n", __func__));
       conn->callbacks.sent_cb = NULL;
-      conn->user_data = NULL;
+      conn->base_.user_data = NULL;
 
       if ((msg->flags & RS_MESSAGE_SENT) == 0)
        {
index 1b07136..b8d7906 100644 (file)
--- a/lib/tcp.c
+++ b/lib/tcp.c
@@ -1,4 +1,4 @@
-/* Copyright 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
@@ -31,7 +31,7 @@ _read_header (struct rs_message *msg)
 {
   size_t n = 0;
 
-  n = bufferevent_read (msg->conn->bev, msg->hdr, RS_HEADER_LEN);
+  n = bufferevent_read (msg->conn->base_.bev, msg->hdr, RS_HEADER_LEN);
   if (n == RS_HEADER_LEN)
     {
       msg->flags |= RS_MESSAGE_HEADER_READ;
@@ -44,7 +44,7 @@ _read_header (struct rs_message *msg)
                                   msg->rpkt->length);
        }
       memcpy (msg->rpkt->data, msg->hdr, RS_HEADER_LEN);
-      bufferevent_setwatermark (msg->conn->bev, EV_READ,
+      bufferevent_setwatermark (msg->conn->base_.bev, EV_READ,
                                msg->rpkt->length - RS_HEADER_LEN, 0);
       rs_debug (("%s: message header read, total msg len=%d\n",
                 __func__, msg->rpkt->length));
@@ -79,7 +79,7 @@ _read_message (struct rs_message *msg)
   rs_debug (("%s: trying to read %d octets of message data\n", __func__,
             msg->rpkt->length - RS_HEADER_LEN));
 
-  n = bufferevent_read (msg->conn->bev,
+  n = bufferevent_read (msg->conn->base_.bev,
                        msg->rpkt->data + RS_HEADER_LEN,
                        msg->rpkt->length - RS_HEADER_LEN);
 
@@ -87,7 +87,7 @@ _read_message (struct rs_message *msg)
 
   if (n == msg->rpkt->length - RS_HEADER_LEN)
     {
-      bufferevent_disable (msg->conn->bev, EV_READ);
+      bufferevent_disable (msg->conn->base_.bev, EV_READ);
       rs_debug (("%s: complete message read\n", __func__));
       msg->flags &= ~RS_MESSAGE_HEADER_READ;
       memset (msg->hdr, 0, sizeof(*msg->hdr));
@@ -119,7 +119,7 @@ _read_message (struct rs_message *msg)
       /* Hand over message to user.  This changes ownership of msg.
         Don't touch it afterwards -- it might have been freed.  */
       if (msg->conn->callbacks.received_cb)
-       msg->conn->callbacks.received_cb (msg, msg->conn->user_data);
+       msg->conn->callbacks.received_cb (msg, msg->conn->base_.user_data);
     }
   else if (n < 0)              /* Buffer frozen.  */
     rs_debug (("%s: buffer frozen when reading message\n", __func__));
@@ -146,7 +146,7 @@ tcp_read_cb (struct bufferevent *bev, void *user_data)
   assert (msg->conn);
   assert (msg->rpkt);
 
-  msg->rpkt->sockfd = msg->conn->fd;
+  msg->rpkt->sockfd = msg->conn->base_.fd;
   msg->rpkt->vps = NULL;        /* FIXME: can this be done when initializing msg? */
 
   /* Read a message header if not already read, return if that
@@ -216,15 +216,15 @@ tcp_event_cb (struct bufferevent *bev, short events, void *user_data)
          rs_debug (("%s: %d: %d (%s)\n", __func__, conn->fd, sockerr,
                     evutil_socket_error_to_string (sockerr)));
          rs_err_conn_push_fl (conn, RSE_SOCKERR, __FILE__, __LINE__,
-                              "%d: %d (%s)", conn->fd, sockerr,
+                              "%d: %d (%s)", conn->base_.fd, sockerr,
                               evutil_socket_error_to_string (sockerr));
        }
 #if defined (RS_ENABLE_TLS)
       if (conn->tls_ssl)       /* FIXME: correct check?  */
        {
-         for (tlserr = bufferevent_get_openssl_error (conn->bev);
+         for (tlserr = bufferevent_get_openssl_error (conn->base_.bev);
               tlserr;
-              tlserr = bufferevent_get_openssl_error (conn->bev))
+              tlserr = bufferevent_get_openssl_error (conn->base_.bev))
            {
              rs_debug (("%s: openssl error: %s\n", __func__,
                         ERR_error_string (tlserr, NULL)));
@@ -251,17 +251,18 @@ tcp_write_cb (struct bufferevent *bev, void *ctx)
   assert (msg->conn);
 
   if (msg->conn->callbacks.sent_cb)
-    msg->conn->callbacks.sent_cb (msg->conn->user_data);
+    msg->conn->callbacks.sent_cb (msg->conn->base_.user_data);
 }
 
 int
 tcp_init_connect_timer (struct rs_connection *conn)
 {
   assert (conn);
+  assert (conn->base_.ctx);
 
   if (conn->tev)
     event_free (conn->tev);
-  conn->tev = evtimer_new (conn->evb, event_conn_timeout_cb, conn);
+  conn->tev = evtimer_new (conn->base_.ctx->evb, event_conn_timeout_cb, conn);
   if (!conn->tev)
     return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
                                "evtimer_new");
index 29e7264..979ee3c 100644 (file)
--- a/lib/tls.c
+++ b/lib/tls.c
@@ -1,4 +1,4 @@
-/* Copyright 2010, 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
@@ -20,7 +20,7 @@
 static struct tls *
 _get_tlsconf (struct rs_connection *conn, const struct rs_realm *realm)
 {
-  struct tls *c = rs_malloc (conn->ctx, sizeof (struct tls));
+  struct tls *c = rs_malloc (conn->base_.ctx, sizeof (struct tls));
 
   if (c)
     {
@@ -123,8 +123,8 @@ rs_tls_init (struct rs_connection *conn)
   SSL *ssl = NULL;
   unsigned long sslerr = 0;
 
-  assert (conn->ctx);
-  ctx = conn->ctx;
+  assert (conn->base_.ctx);
+  ctx = conn->base_.ctx;
 
   tlsconf = _get_tlsconf (conn, conn->active_peer->realm);
   if (!tlsconf)
index f598804..71d7003 100644 (file)
--- a/lib/udp.c
+++ b/lib/udp.c
@@ -1,4 +1,4 @@
-/* Copyright 2011 NORDUnet A/S. All rights reserved.
+/* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
    See LICENSE for licensing information.  */
 
 #if defined HAVE_CONFIG_H
@@ -45,7 +45,7 @@ _send (struct rs_connection *conn, int fd)
   /* If there are more messages in queue, add the write event again.  */
   if (msg->conn->out_queue)
     {
-      r = event_add (msg->conn->wev, NULL);
+      r = event_add (msg->conn->base_.wev, NULL);
       if (r < 0)
        return rs_err_conn_push_fl (msg->conn, RSE_EVENT, __FILE__, __LINE__,
                                    "event_add: %s", evutil_gai_strerror (r));
@@ -121,7 +121,7 @@ _evcb (evutil_socket_t fd, short what, void *user_data)
       /* Hand over message to user.  This changes ownership of msg.
         Don't touch it afterwards -- it might have been freed.  */
       if (msg->conn->callbacks.received_cb)
-       msg->conn->callbacks.received_cb (msg, msg->conn->user_data);
+       msg->conn->callbacks.received_cb (msg, msg->conn->base_.user_data);
     }
   else if (what & EV_WRITE)
     {
@@ -135,7 +135,7 @@ _evcb (evutil_socket_t fd, short what, void *user_data)
       if (msg->conn->out_queue)
        if (_send (msg->conn, fd) == RSE_OK)
          if (msg->conn->callbacks.sent_cb)
-           msg->conn->callbacks.sent_cb (msg->conn->user_data);
+           msg->conn->callbacks.sent_cb (msg->conn->base_.user_data);
     }
 
 #if defined (DEBUG)
@@ -147,16 +147,18 @@ _evcb (evutil_socket_t fd, short what, void *user_data)
 int
 udp_init (struct rs_connection *conn, struct rs_message *msg)
 {
-  assert (!conn->bev);
+  assert (!conn->base_.bev);
 
-  conn->rev = event_new (conn->evb, conn->fd, EV_READ|EV_PERSIST, _evcb, NULL);
-  conn->wev = event_new (conn->evb, conn->fd, EV_WRITE, _evcb, NULL);
-  if (!conn->rev || !conn->wev)
+  conn->base_.rev = event_new (conn->base_.ctx->evb, conn->base_.fd,
+                             EV_READ|EV_PERSIST, _evcb, NULL);
+  conn->base_.wev = event_new (conn->base_.ctx->evb, conn->base_.fd,
+                             EV_WRITE, _evcb, NULL);
+  if (!conn->base_.rev || !conn->base_.wev)
     {
-      if (conn->rev)
+      if (conn->base_.rev)
        {
-         event_free (conn->rev);
-         conn->rev = NULL;
+         event_free (conn->base_.rev);
+         conn->base_.rev = NULL;
        }
       /* ENOMEM _or_ EINVAL but EINVAL only if we use EV_SIGNAL, at
         least for now (libevent-2.0.5).  */
@@ -169,10 +171,13 @@ int
 udp_init_retransmit_timer (struct rs_connection *conn)
 {
   assert (conn);
+  assert (conn->base_.ctx);
+  assert (conn->base_.ctx->evb);
 
   if (conn->tev)
     event_free (conn->tev);
-  conn->tev = evtimer_new (conn->evb, event_retransmit_timeout_cb, conn);
+  conn->tev =
+    evtimer_new (conn->base_.ctx->evb, event_retransmit_timeout_cb, conn);
   if (!conn->tev)
     return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
                                "evtimer_new");