Refactoring in preparation for handling more cases than client sending one packet.
authorLinus Nordberg <linus@nordu.net>
Wed, 29 Sep 2010 19:53:43 +0000 (21:53 +0200)
committerLinus Nordberg <linus@nordu.net>
Wed, 29 Sep 2010 19:53:43 +0000 (21:53 +0200)
lib/err.c
lib/examples/client.c
lib/libradsec-impl.h
lib/packet.c
lib/radsec.c

index 74edeb0..4c88ce1 100644 (file)
--- a/lib/err.c
+++ b/lib/err.c
@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include <string.h>
 #include <assert.h>
 #include "libradsec.h"
 #include "libradsec-impl.h"
@@ -27,6 +28,7 @@ const char *_errtxt[] = {
   "ERR "                       /*  RSE_ */
   "some error"                 /* 21 RSE_SOME_ERROR */
 };
+#define ERRTXT_SIZE (sizeof(_errtxt) / sizeof(*_errtxt))
 
 static struct rs_error *
 _err_new (unsigned int code, const char *file, int line, const char *fmt, va_list args)
@@ -39,8 +41,16 @@ _err_new (unsigned int code, const char *file, int line, const char *fmt, va_lis
       int n;
       memset (err, 0, sizeof(struct rs_error));
       err->code = code;
-      n = vsnprintf (err->buf, sizeof(err->buf), fmt, args);
-      if (n > 0)
+      if (fmt)
+       n = vsnprintf (err->buf, sizeof(err->buf), fmt, args);
+      else
+       {
+         strncpy (err->buf,
+                  err->code < ERRTXT_SIZE ? _errtxt[err->code] : "",
+                  sizeof(err->buf));
+         n = strlen (err->buf);
+       }
+      if (n >= 0)
        {
          char *sep = strrchr (file, '/');
          if (sep)
index 14555c7..d7e7270 100644 (file)
@@ -38,9 +38,17 @@ rsx_client (const char *srvname, int srvport)
     return rs_conn_err_pop (conn);
   req = NULL;
 
+#if 0
+  if (rs_packet_recv (conn, &resp))
+    return rs_conn_err_pop (conn);
+#if defined (DEBUG)
+  rs_dump_packet (resp);
+#endif
+#endif
+
   rs_conn_destroy (conn);
   rs_context_destroy (h);
-  return 0;
+  return NULL;
 }
 
 int
@@ -53,8 +61,10 @@ main (int argc, char *argv[])
   host = strsep (argv + 1, ":");
   port = atoi (argv[1]);
   err = rsx_client (host, port);
-  if (!err)
-    return -1;
-  fprintf (stderr, "%s\n", rs_err_msg (err, 0));
-  return rs_err_code (err, 1);
+  if (err)
+    {
+      fprintf (stderr, "%s\n", rs_err_msg (err, 0));
+      return rs_err_code (err, 1);
+    }
+  return 0;
 }
index e51c54c..a4ce7c2 100644 (file)
@@ -71,6 +71,8 @@ struct rs_peer {
     struct rs_connection *conn;
     struct evutil_addrinfo *addr;
     int s;                     /* Socket.  */
+    char is_connecting;
+    char is_connected;
     char *secret;
     int timeout;               /* client only */
     int tries;                 /* client only */
@@ -80,6 +82,7 @@ struct rs_peer {
 struct rs_connection {
     struct rs_handle *ctx;
     struct event_base *evb;
+    struct bufferevent *bev;
     enum rs_conn_type type;
     struct rs_credentials transport_credentials;
     struct rs_conn_callbacks callbacks;
@@ -98,9 +101,6 @@ struct rs_attr {
     VALUE_PAIR *vp;
 };
 
-/* Internal functions.  */
-int rs_conn_open(struct rs_connection *conn);
-
 /* Convenience macros.  */
 #define rs_calloc(h, nmemb, size) \
     (h->alloc_scheme.calloc ? h->alloc_scheme.calloc : calloc)(nmemb, size)
index 652c495..90c8c31 100644 (file)
@@ -66,11 +66,19 @@ static void
 _event_cb (struct bufferevent *bev, short events, void *ctx)
 {
   struct rs_packet *pkt = (struct rs_packet *) ctx;
+  struct rs_connection *conn;
+  struct rs_peer *p;
 
   assert (pkt);
   assert (pkt->conn);
+  assert (pkt->conn->active_peer);
+  conn = pkt->conn;
+  p = conn->active_peer;
+
+  p->is_connecting = 0;
   if (events & BEV_EVENT_CONNECTED)
     {
+      p->is_connected = 1;
 #if defined (DEBUG)
       fprintf (stderr, "%s: connected\n", __func__);
 #endif
@@ -110,32 +118,107 @@ _write_cb (struct bufferevent *bev, void *ctx)
   rs_packet_destroy (pkt);
 }
 
-int
-rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data)
+static int
+_init_evb (struct rs_connection *conn)
 {
-  struct bufferevent *bev;
-  struct rs_peer *p;
+  if (!conn->evb)
+    {
+#if defined (DEBUG)
+      event_enable_debug_mode ();
+#endif
+      conn->evb = event_base_new ();
+      if (!conn->evb)
+       return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+                                   "event_base_new");
+    }
+  return RSE_OK;
+}
 
-  assert (pkt->rpkt);
+static int
+_init_socket (struct rs_connection *conn, struct rs_peer *p)
+{
+  if (p->s < 0)
+    {
+      assert (p->addr);
+      p->s = socket (p->addr->ai_family, p->addr->ai_socktype,
+                    p->addr->ai_protocol);
+      if (p->s < 0)
+       return rs_conn_err_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
+                                   strerror (errno));
+    }
+  return RSE_OK;
+}
 
-  if (rs_conn_open (conn))
-    return -1;
-  p = conn->active_peer;
-  assert (p);
+static struct rs_peer *
+_pick_peer (struct rs_connection *conn)
+{
+  if (!conn->active_peer)
+    conn->active_peer = conn->peers;
+  return conn->active_peer;
+}
 
-  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)
+static int
+_init_bev (struct rs_connection *conn, struct rs_peer *peer,
+          struct rs_packet *pkt)
+{
+  if (!conn->bev)
     {
-      bufferevent_free (bev);
-      return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
-                                 "bufferevent_socket_connect");
+      conn->bev = bufferevent_socket_new (conn->evb, peer->s, 0);
+      if (!conn->bev)
+       return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+                                   "bufferevent_socket_new");
+      bufferevent_setcb (conn->bev, NULL, _write_cb, _event_cb, pkt);
     }
+  return RSE_OK;
+}
+
+static void
+_do_connect (struct rs_peer *p)
+{
+  if (bufferevent_socket_connect (p->conn->bev, p->addr->ai_addr,
+                                 p->addr->ai_addrlen) < 0)
+    rs_conn_err_push_fl (p->conn, RSE_EVENT, __FILE__, __LINE__,
+                          "bufferevent_socket_connect");
+  else
+    p->is_connecting = 1;
+}
+
+static int
+_conn_open(struct rs_connection *conn, struct rs_packet *pkt)
+{
+  struct rs_peer *p;
+
+  if (_init_evb (conn))
+    return -1;
+
+  p = _pick_peer (conn);
+  if (!p)
+    return rs_conn_err_push_fl (conn, RSE_NOPEER, __FILE__, __LINE__, NULL);
+
+  if (_init_socket (conn, p))
+    return -1;
+
+  if (_init_bev (conn, p, pkt))
+    return -1;
 
-  bufferevent_setcb (bev, NULL, _write_cb, _event_cb, pkt);
+  if (!p->is_connected)
+    if (!p->is_connecting)
+      _do_connect (p);
+
+  return RSE_OK;
+}
+
+int
+rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data)
+{
+  assert (conn);
+  assert (pkt->rpkt);
+  if (_conn_open (conn, pkt))
+    return -1;
+  assert (conn->evb);
+  assert (conn->bev);
+  assert (conn->active_peer);
+  assert (conn->active_peer->s >= 0);
   event_base_dispatch (conn->evb);
 #if defined (DEBUG)
   fprintf (stderr, "%s: event loop done\n", __func__);
@@ -147,13 +230,18 @@ rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data)
 
 int rs_packet_receive(struct rs_connection *conn, struct rs_packet **pkt)
 {
-  return rs_conn_err_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__,
-                             "%s: NYI", __func__);
+  //struct bufferevent *bev;
+
+  //skalleper;
+  //bufferevent_enable(bev, EV_READ);
+  return 0;                    /* FIXME */
 }
 
+
 void
 rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr)
 {
   pairadd (&pkt->rpkt->vps, attr->vp);
   attr->pkt = pkt;
 }
+
index 82576e1..72d7f5f 100644 (file)
@@ -128,35 +128,53 @@ _resolv (struct rs_connection *conn, const char *hostname, int port)
   return res;                  /* Simply use first result.  */
 }
 
+static struct rs_peer *
+_peer_new (struct rs_connection *conn, const char *hostname, int port)
+{
+  struct rs_peer *p;
+  struct evutil_addrinfo *addr;
+
+  addr = _resolv (conn, hostname, port);
+  if (!addr)
+    return NULL;
+
+  p = (struct rs_peer *) malloc (sizeof(*p));
+  if (p)
+    {
+      memset (p, 0, sizeof(struct rs_peer));
+      p->conn = conn;
+      p->s = -1;
+      p->addr = addr;
+      p->next = conn->peers;
+      if (conn->peers)
+       conn->peers->next = p;
+      else
+       conn->peers = p;
+    }
+  else
+    {
+      evutil_freeaddrinfo (addr);
+      rs_conn_err_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
+    }
+  return p;
+}
+
 int
 rs_conn_add_server(struct rs_connection *conn, struct rs_peer **server,
                   rs_conn_type_t type, const char *hostname, int port)
 {
   struct rs_peer *srv;
-  struct evutil_addrinfo *addr;
 
   if (conn->type == RS_CONN_TYPE_NONE)
     conn->type = type;
   else if (conn->type != type)
     return rs_conn_err_push (conn, RSE_CONN_TYPE_MISMATCH, NULL);
 
-  addr = _resolv (conn, hostname, port);
-  if (!addr)
-    return -1;
-
-  srv = (struct rs_peer *) malloc (sizeof(struct rs_peer));
+  srv = _peer_new (conn, hostname, port);
   if (srv)
     {
-      memset (srv, 0, sizeof(struct rs_peer));
-      srv->conn = conn;
-      srv->addr = addr;
       srv->timeout = 10;
       srv->tries = 3;
-      srv->next = conn->peers;
-      if (conn->peers)
-       conn->peers->next = srv;
-      else
-       conn->peers = srv;
     }
   if (*server)
     *server = srv;
@@ -188,7 +206,6 @@ int rs_conn_add_listener(struct rs_connection *conn, rs_conn_type_t type, const
                              "%s: NYI", __func__);
 }
 
-
 void
 rs_conn_destroy(struct rs_connection *conn)
 {
@@ -232,49 +249,3 @@ int rs_conn_get_current_server(struct rs_connection *conn, const char *name, siz
                              "%s: NYI", __func__);
 }
 
-/* Non-public.  */
-int
-rs_conn_open(struct rs_connection *conn)
-{
-  int s;
-  struct rs_peer *p;
-
-  if (conn->active_peer)
-    return RSE_OK;
-  p = conn->peers;
-  if (!p)
-    return rs_conn_err_push_fl (conn, RSE_NOPEER, __FILE__, __LINE__, NULL);
-
-  s = socket (p->addr->ai_family, p->addr->ai_socktype, p->addr->ai_protocol);
-  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).  */
-      EVUTIL_CLOSESOCKET (s);
-      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;
-}