summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nordberg <linus@nordu.net>2010-09-29 15:52:39 +0200
committerLinus Nordberg <linus@nordu.net>2010-09-29 15:52:39 +0200
commitb10a02e5f3a7dd184ada869015e438e63bca52bf (patch)
tree70c74d012d2a89c1a1efefa5afc0787de0b84368
parente2633633030e62994ca41ff62006e3e40517c73a (diff)
WIP -- connecting and sending a packet using libevent.
-rw-r--r--lib/err.c4
-rw-r--r--lib/examples/Makefile2
-rw-r--r--lib/examples/client.c12
-rw-r--r--lib/libradsec-impl.h1
-rw-r--r--lib/libradsec.h6
-rw-r--r--lib/packet.c88
-rw-r--r--lib/radsec.c22
7 files changed, 108 insertions, 27 deletions
diff --git a/lib/err.c b/lib/err.c
index b0f05c6..74edeb0 100644
--- a/lib/err.c
+++ b/lib/err.c
@@ -13,8 +13,8 @@ const char *_errtxt[] = {
"FreeRadius error" /* 6 RSE_FR */
"bad hostname or port" /* 7 RSE_BADADDR */
"no peer configured" /* 8 RSE_NOPEER */
- "ERR 9" /* RSE_ */
- "ERR 10" /* RSE_ */
+ "libevent error" /* 9 RSE_EVENT */
+ "connection error" /* 10 RSE_CONNERR */
"ERR 11" /* RSE_ */
"ERR 12" /* RSE_ */
"ERR 13" /* RSE_ */
diff --git a/lib/examples/Makefile b/lib/examples/Makefile
index a9876da..f9f2ee1 100644
--- a/lib/examples/Makefile
+++ b/lib/examples/Makefile
@@ -6,7 +6,7 @@ blocking.o: blocking.c blocking.h ../libradsec-base.h ../libradsec.h
$(CC) $(CFLAGS) -c -I .. $^
client: client.c ../libradsec.a ../libradsec.h ../libradsec-impl.h
- $(CC) $(CFLAGS) -o $@ $< -L /usr/lib/freeradius -lfreeradius-radius -L .. -lradsec -L /usr/local/lib -levent
+ $(CC) $(CFLAGS) -o $@ $< -L /usr/lib/freeradius -lfreeradius-radius -L .. -lradsec -L /usr/local/lib -levent_core
clean:
-rm *.o client
diff --git a/lib/examples/client.c b/lib/examples/client.c
index a6b7999..2304e49 100644
--- a/lib/examples/client.c
+++ b/lib/examples/client.c
@@ -4,6 +4,7 @@
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
+#include <event2/event.h>
#include "../libradsec.h"
#include "../debug.h"
@@ -18,14 +19,13 @@ rsx_client (const char *srvname, int srvport)
struct rs_connection *conn;
struct rs_peer *server;
struct rs_packet *req;
- //struct rs_packet *resp;
if (rs_context_create (&h, "/usr/share/freeradius/dictionary"))
return NULL;
if (rs_conn_create (h, &conn))
return rs_conn_err_pop (conn);
- if (rs_conn_add_server (conn, &server, RS_CONN_TYPE_UDP, srvname, srvport))
+ if (rs_conn_add_server (conn, &server, RS_CONN_TYPE_TCP, srvname, srvport))
return rs_conn_err_pop (conn);
rs_server_set_timeout (server, 10);
rs_server_set_tries (server, 3);
@@ -38,14 +38,6 @@ rsx_client (const char *srvname, int srvport)
return rs_conn_err_pop (conn);
req = NULL;
-#if 0
- printf ("waiting for response\n");
- if (rs_packet_recv (conn, &resp))
- return rs_conn_err_pop (conn);
- printf ("got response\n");
- rs_dump_packet (resp);
-#endif
-
rs_conn_destroy (conn);
rs_context_destroy (h);
return 0;
diff --git a/lib/libradsec-impl.h b/lib/libradsec-impl.h
index 939cdd9..e51c54c 100644
--- a/lib/libradsec-impl.h
+++ b/lib/libradsec-impl.h
@@ -79,6 +79,7 @@ struct rs_peer {
struct rs_connection {
struct rs_handle *ctx;
+ struct event_base *evb;
enum rs_conn_type type;
struct rs_credentials transport_credentials;
struct rs_conn_callbacks callbacks;
diff --git a/lib/libradsec.h b/lib/libradsec.h
index 255c0f5..2ccafe2 100644
--- a/lib/libradsec.h
+++ b/lib/libradsec.h
@@ -14,6 +14,8 @@ enum rs_err_code {
RSE_FR = 6,
RSE_BADADDR = 7,
RSE_NOPEER = 8,
+ RSE_EVENT = 9,
+ RSE_CONNERR = 10,
RSE_SOME_ERROR = 21,
};
@@ -48,7 +50,7 @@ int rs_context_config_read(struct rs_handle *ctx, const char *config_file);
int rs_conn_create(struct rs_handle *ctx, struct rs_connection **conn);
int rs_conn_add_server(struct rs_connection *conn, struct rs_peer **server, rs_conn_type_t type, const char *hostname, int port);
int rs_conn_add_listener(struct rs_connection *conn, rs_conn_type_t type, const char *hostname, int port);
-void rs_conn_destroy(struct rs_connection *conn);
+void rs_conn_destroy(struct rs_connection *conn);
int rs_conn_set_eventbase(struct rs_connection *conn, struct event_base *eb);
int rs_conn_set_callbacks(struct rs_connection *conn, struct rs_conn_callbacks *cb);
int rs_conn_select_server(struct rs_connection *conn, const char *name);
@@ -69,7 +71,7 @@ void rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr);
int rs_attr_create(struct rs_connection *conn, struct rs_attr **attr, const char *type, const char *val);
void rs_attr_destroy(struct rs_attr *attr);
-int rs_packet_send(struct rs_connection *conn, const struct rs_packet *pkt, void *user_data);
+int rs_packet_send(struct rs_connection *conn, struct rs_packet *pkt, void *data);
int rs_packet_recv(struct rs_connection *conn, struct rs_packet **pkt);
int rs_ctx_err_push(struct rs_handle *ctx, int code, const char *fmt, ...);
diff --git a/lib/packet.c b/lib/packet.c
index eefb5eb..652c495 100644
--- a/lib/packet.c
+++ b/lib/packet.c
@@ -1,6 +1,8 @@
#include <string.h>
#include <assert.h>
#include <freeradius/libradius.h>
+#include <event2/event.h>
+#include <event2/bufferevent.h>
#include "libradsec.h"
#include "libradsec-impl.h"
#if defined DEBUG
@@ -29,6 +31,7 @@ _packet_create (struct rs_connection *conn, struct rs_packet **pkt_out,
return rs_conn_err_push (conn, RSE_NOMEM, __func__);
}
memset (p, 0, sizeof (struct rs_packet));
+ p->conn = conn;
p->rpkt = rpkt;
*pkt_out = p;
@@ -59,26 +62,87 @@ rs_packet_create_acc_request (struct rs_connection *conn,
return RSE_OK;
}
+static void
+_event_cb (struct bufferevent *bev, short events, void *ctx)
+{
+ struct rs_packet *pkt = (struct rs_packet *) ctx;
+
+ assert (pkt);
+ assert (pkt->conn);
+ if (events & BEV_EVENT_CONNECTED)
+ {
+#if defined (DEBUG)
+ fprintf (stderr, "%s: connected\n", __func__);
+#endif
+ rad_encode (pkt->rpkt, NULL, pkt->conn->active_peer->secret);
+#if defined (DEBUG)
+ fprintf (stderr, "%s: about to send this to %s:\n", __func__, "<fixme>");
+ rs_dump_packet (pkt);
+#endif
+ if (bufferevent_write(bev, pkt->rpkt->data, pkt->rpkt->data_len))
+ rs_conn_err_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
+ "bufferevent_write");
+ /* Packet will be freed in write callback. */
+ }
+ else if (events & BEV_EVENT_ERROR)
+ rs_conn_err_push_fl (pkt->conn, RSE_CONNERR, __FILE__, __LINE__, NULL);
+}
+
+void
+rs_packet_destroy(struct rs_packet *pkt)
+{
+ rad_free (&pkt->rpkt);
+ rs_free (pkt->conn->ctx, pkt);
+}
+
+static void
+_write_cb (struct bufferevent *bev, void *ctx)
+{
+ struct rs_packet *pkt = (struct rs_packet *) ctx;
+
+ assert (pkt);
+ assert (pkt->conn);
+#if defined (DEBUG)
+ fprintf (stderr, "%s: packet written, breaking event loop\n", __func__);
+#endif
+ if (event_base_loopbreak (pkt->conn->evb) < 0)
+ abort (); /* FIXME */
+ rs_packet_destroy (pkt);
+}
+
int
-rs_packet_send (struct rs_connection *conn, const struct rs_packet *pkt,
- void *user_data)
+rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data)
{
+ struct bufferevent *bev;
+ struct rs_peer *p;
+
assert (pkt->rpkt);
- if (!conn->active_peer)
+ if (rs_conn_open (conn))
+ return -1;
+ p = conn->active_peer;
+ assert (p);
+
+ assert (conn->active_peer->s >= 0);
+ bev = bufferevent_socket_new (conn->evb, conn->active_peer->s, 0);
+ if (!bev)
+ return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+ "bufferevent_socket_new");
+ if (bufferevent_socket_connect (bev, p->addr->ai_addr, p->addr->ai_addrlen) < 0)
{
- int err = rs_conn_open (conn);
- if (err)
- return err;
- }
- rad_encode (pkt->rpkt, NULL, conn->active_peer->secret);
+ bufferevent_free (bev);
+ return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+ "bufferevent_socket_connect");
+ }
+
+ bufferevent_setcb (bev, NULL, _write_cb, _event_cb, pkt);
+ event_base_dispatch (conn->evb);
#if defined (DEBUG)
- fprintf (stderr, "%s: about to send this to %s:\n", __func__, "<fixme>");
- rs_dump_packet (pkt);
+ fprintf (stderr, "%s: event loop done\n", __func__);
+ assert (event_base_got_break(conn->evb));
#endif
- return rs_conn_err_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__,
- "%s: NYI", __func__);
+ return RSE_OK;
}
int rs_packet_receive(struct rs_connection *conn, struct rs_packet **pkt)
diff --git a/lib/radsec.c b/lib/radsec.c
index 97f62e6..82576e1 100644
--- a/lib/radsec.c
+++ b/lib/radsec.c
@@ -5,6 +5,7 @@
#include <libgen.h>
#include <freeradius/libradius.h>
+#include <event2/event.h>
#include <event2/util.h>
#include "libradsec.h"
#include "libradsec-impl.h"
@@ -202,6 +203,9 @@ rs_conn_destroy(struct rs_connection *conn)
if (p->secret)
rs_free (conn->ctx, p->secret);
}
+
+ if (conn->evb)
+ event_base_free (conn->evb);
}
int rs_conn_set_eventbase(struct rs_connection *conn, struct event_base *eb)
@@ -245,6 +249,7 @@ rs_conn_open(struct rs_connection *conn)
if (s < 0)
return rs_conn_err_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
strerror (errno));
+#if 0 /* let librevent do this in rs_packet_send() */
if (connect (s, p->addr->ai_addr, p->addr->ai_addrlen))
{
/* TODO: handle nonblocking sockets (EINTR, EAGAIN). */
@@ -252,6 +257,23 @@ rs_conn_open(struct rs_connection *conn)
return rs_conn_err_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
strerror (errno));
}
+#endif
+
+ if (!conn->evb)
+ {
+#if defined (DEBUG)
+ event_enable_debug_mode ();
+#endif
+ conn->evb = event_base_new ();
+ }
+
+ if (!conn->evb)
+ {
+ EVUTIL_CLOSESOCKET (s);
+ return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+ "event_base_new");
+ }
+
p->s = s;
conn->active_peer = p;
return RSE_OK;