From ec47efe2b20e8ff21489744caaf646c692243860 Mon Sep 17 00:00:00 2001
From: Linus Nordberg <linus@nordberg.se>
Date: Mon, 18 Feb 2013 17:12:20 +0100
Subject: WIP commit for listener support.

---
 lib/include/radsec/radsec-impl.h  | 76 ++++++++++++++++++++++++++++++++-------
 lib/include/radsec/radsec.h       | 23 ++++++++++--
 lib/include/radsec/request-impl.h |  3 +-
 lib/include/radsec/request.h      |  3 +-
 4 files changed, 88 insertions(+), 17 deletions(-)

(limited to 'lib/include')

diff --git a/lib/include/radsec/radsec-impl.h b/lib/include/radsec/radsec-impl.h
index 32753ef..fecf8f2 100644
--- a/lib/include/radsec/radsec-impl.h
+++ b/lib/include/radsec/radsec-impl.h
@@ -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: */
diff --git a/lib/include/radsec/radsec.h b/lib/include/radsec/radsec.h
index 0a43f6f..021f677 100644
--- a/lib/include/radsec/radsec.h
+++ b/lib/include/radsec/radsec.h
@@ -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);
diff --git a/lib/include/radsec/request-impl.h b/lib/include/radsec/request-impl.h
index 9af1394..dbb4244 100644
--- a/lib/include/radsec/request-impl.h
+++ b/lib/include/radsec/request-impl.h
@@ -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
diff --git a/lib/include/radsec/request.h b/lib/include/radsec/request.h
index 05b5daa..b78411a 100644
--- a/lib/include/radsec/request.h
+++ b/lib/include/radsec/request.h
@@ -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
-- 
cgit v1.1