WIP -- connecting and sending a packet using libevent.
authorLinus Nordberg <linus@nordu.net>
Wed, 29 Sep 2010 13:52:39 +0000 (15:52 +0200)
committerLinus Nordberg <linus@nordu.net>
Wed, 29 Sep 2010 13:52:39 +0000 (15:52 +0200)
lib/err.c
lib/examples/Makefile
lib/examples/client.c
lib/libradsec-impl.h
lib/libradsec.h
lib/packet.c
lib/radsec.c

index b0f05c6..74edeb0 100644 (file)
--- 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_ */
index a9876da..f9f2ee1 100644 (file)
@@ -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
index a6b7999..2304e49 100644 (file)
@@ -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;
index 939cdd9..e51c54c 100644 (file)
@@ -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;
index 255c0f5..2ccafe2 100644 (file)
@@ -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, ...);
index eefb5eb..652c495 100644 (file)
@@ -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)
index 97f62e6..82576e1 100644 (file)
@@ -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;