Low level connect and read working, kind of. At least TCP.
authorLinus Nordberg <linus@nordu.net>
Thu, 2 Sep 2010 22:58:55 +0000 (00:58 +0200)
committerLinus Nordberg <linus@nordu.net>
Thu, 2 Sep 2010 22:58:55 +0000 (00:58 +0200)
Next: serializing.

lib/Makefile [new file with mode: 0644]
lib/base.c [new file with mode: 0644]
lib/blocking.c [new file with mode: 0644]
lib/blocking.h [new file with mode: 0644]
lib/libradsec-base.h
lib/libradsec-levent.h
lib/libradsec.h
lib/test-blocking.c [new file with mode: 0644]

diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644 (file)
index 0000000..71112cb
--- /dev/null
@@ -0,0 +1,7 @@
+blocking.o: blocking.c blocking.h libradsec-base.h libradsec.h
+base.o: base.c libradsec-base.h libradsec.h
+test-blocking: test-blocking.c blocking.o base.o
+       $(CC) -o $@ $^
+
+doc:
+       doxygen
diff --git a/lib/base.c b/lib/base.c
new file mode 100644 (file)
index 0000000..38086c0
--- /dev/null
@@ -0,0 +1,113 @@
+#include <sys/socket.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "libradsec-base.h"
+
+static int
+do_connect(int type,
+          const struct sockaddr *addr,
+          socklen_t addrlen)
+{
+  int s;
+
+  s = socket(AF_INET, type, 0); /* FIXME: do AF_INET6 too */
+  if (s >= 0)
+      if (connect(s, addr, addrlen)) {
+         close(s);
+         s = -1;
+      }
+  return s;
+}
+
+int
+rs_connect(const struct rs_config *conf,
+          const struct sockaddr *addr,
+          socklen_t addrlen)
+{
+    switch (conf->conn_type)
+    {
+    case RS_CONN_TYPE_UDP:
+       return do_connect(SOCK_DGRAM, addr, addrlen);
+    case RS_CONN_TYPE_TCP:
+       return do_connect(SOCK_STREAM, addr, addrlen);
+       /* fall thru */
+    case RS_CONN_TYPE_TLS:
+       /* fall thru */
+    case RS_CONN_TYPE_DTLS:
+       /* fall thru */
+    default:
+       errno = ENOSYS;
+       return -1;
+    }
+}
+
+int
+rs_disconnect( const struct rs_config *conf, int fd)
+{
+    switch (conf->conn_type)
+    {
+    case RS_CONN_TYPE_UDP:
+       return close(fd);
+    case RS_CONN_TYPE_TCP:
+       shutdown(fd, SHUT_RDWR);
+       return close(fd);
+    case RS_CONN_TYPE_TLS:
+       /* fall thru */
+    case RS_CONN_TYPE_DTLS:
+       /* fall thru */
+    default:
+       errno = ENOSYS;
+       return -1;
+    }
+}
+
+struct rs_packet *
+rs_packet_new(const struct rs_config *ctx,
+             const uint8_t buf[RS_HEADER_LEN],
+             size_t *count)
+{
+    struct rs_packet *p =
+       (ctx->alloc_scheme.malloc ? ctx->alloc_scheme.malloc : malloc)(20);
+    if (p) {
+       p->code = buf[0];
+       p->id = buf[1];
+       if (count)
+           *count = 256 * buf[2] + buf[3];
+    }
+    return p;
+}
+
+struct rs_packet *
+rs_packet_parse(const struct rs_config *ctx,
+               struct rs_packet *packet,
+               const uint8_t *buf,
+               size_t buflen)
+{
+    if (buflen < 16) {
+       rs_packet_free(ctx, packet);
+       errno = EPROTO;
+       return NULL;
+    }
+    memcpy(packet->auth, buf, 16);
+    /* TODO: copy attributes starting at buf[16].  */
+    return packet;
+}
+
+void
+rs_packet_free(const struct rs_config *ctx,
+              struct rs_packet *packet)
+{
+    (ctx->alloc_scheme.free ? ctx->alloc_scheme.free : free)(packet);
+}
+
+ssize_t
+rs_packet_serialize(const struct rs_packet *packet,
+                   uint8_t *buf,
+                   size_t buflen)
+{
+    fixme;
+}
+
+/* Local Variables: */
+/* c-file-style: "stroustrup" */
+/* End: */
diff --git a/lib/blocking.c b/lib/blocking.c
new file mode 100644 (file)
index 0000000..6ee4ad3
--- /dev/null
@@ -0,0 +1,67 @@
+/* Example usage of libradsec-base, using blocking i/o.  */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include "blocking.h"
+
+struct rs_packet *
+next_packet (const struct rs_config *ctx, int fd)
+{
+  uint8_t hdr[RS_HEADER_LEN];
+  uint8_t *buf;
+  size_t len;
+  struct rs_packet *p;
+  ssize_t n;
+
+  /* Read fixed length header.  */
+  n = 0;
+  while (n < RS_HEADER_LEN)
+    n += read (fd, hdr, RS_HEADER_LEN - n);
+
+  p = rs_packet_new (ctx, hdr, &len);
+  fprintf (stderr, "DEBUG: len: %d\n", len);
+  if (p)
+    {
+      /* Read the rest of the packet.  */
+      buf = malloc (len);
+      if (buf)
+       {
+         n = 0;
+         while (n < len)
+           n += read (fd, buf, len - n);
+         p = rs_packet_parse (ctx, p, buf, len);
+         free (buf);
+       }
+    }
+
+  return p;
+}
+
+int
+send_packet(const struct rs_config *ctx, int fd, struct rs_packet *p)
+{
+  uint8_t *buf = NULL;
+  ssize_t n = -20;           /* Arbitrary packet size -- a guess.  */
+
+  while (n < 0)
+    {
+      buf = realloc (buf, -n);
+      if (buf == NULL)
+       return -1;
+      n = rs_packet_serialize (p, buf, -n);
+    }
+
+  while (n)
+    {
+      ssize_t count = write (fd, buf, n);
+      if (count == -1)
+       return -1;
+      n -= count;
+    }
+
+  free (buf);
+  rs_packet_free (ctx, p);
+  return 0;
+}
diff --git a/lib/blocking.h b/lib/blocking.h
new file mode 100644 (file)
index 0000000..04a07a8
--- /dev/null
@@ -0,0 +1,4 @@
+#include "libradsec-base.h"
+
+struct rs_packet *next_packet (const struct rs_config *ctx, int fd);
+int send_packet (const struct rs_config *ctx, int fd, struct rs_packet *p);
index cb4308d..a972bf2 100644 (file)
@@ -1,43 +1,12 @@
-/** @file libradsec-minimal.h
+/** @file libradsec-base.h
     @brief Low level API for libradsec.  */
 
 /* FIXME: License blurb goes here.  */
 
-#include "libevent.h"
-
-/* Example usage.  */
-#if 0
-{
-  fd = rs_connect (address, 0, NULL);
-  if (!fd)
-    /* check errno */ ;
-  n = read (fd, buf, buflen);
-  struct rs_packet *p = rs_packet_new (buf, buflen, &count);
-  if (!p)
-    {
-      if (count < 0)
-       /* check errno */ ;
-      else
-       /* need another COUNT octets */ ;
-    }
-  else
-    /* next unused octet is at buf+count */
-
-  n = rs_packet_serialize (p, buf, buflen);
-  if (n < 0)
-    /* invalid packet */ ;
-  else if (n == 0)
-    /* out of buffer space */ ;
-  else
-    write (fd, buf, n);
-
-  if (p)
-    rs_packet_free(p);
-  if (fd)
-    rs_disconnect(fd);
-}
-#endif
-
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/socket.h>
+#include "libradsec.h"
 
 /* Function prototypes.  */
 
@@ -49,9 +18,9 @@
 
     @return A file descriptor or -1 if an error occurred, in which
     case errno is set appropriately.  */
-int rs_connect(const struct sockaddr_storage *addr,
-              enum rs_conn_type type,
-              const struct rs_credentials *cred);
+int rs_connect(const struct rs_config *conf,
+              const struct sockaddr *addr,
+              socklen_t addrlen);
 
 /** Disconnect.
 
@@ -59,11 +28,14 @@ int rs_connect(const struct sockaddr_storage *addr,
 
     @return 0 on success or -1 if an error occurred, in which case
     errno is set appropriately.  */
-int rs_disconnect(int fd);
+int rs_disconnect(const struct rs_config *conf,
+                 int fd);
 
 /** Allocate and initialize a packet from a buffer containing a packet
     as seen on the wire.  Free the packet using @a rs_packet_free().
 
+FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
+
     @param buf Buffer with on-the-wire data with packet.
     @param buflen Number of octets in @a buf.
 
@@ -71,19 +43,29 @@ int rs_disconnect(int fd);
     successful construction of a packet (return !NULL) or number of
     octets needed for a complete packet (return NULL).
 
+FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
+
     @return Packet or NULL on error or not enough data in @a buf.  If
     return value is NULL and @a count is < 0, an error has occurred
     and errno is set appropriately.  If return value is NULL and @a
     count is > 0 it shows the number of bytes needed to complete the
     packet.  */
-struct rs_packet *rs_packet_new(const uint8_t *buf,
-                               size_t buflen,
-                               ssize_t *count);
+struct rs_packet *rs_packet_new(const struct rs_config *ctx,
+                               const uint8_t buf[RS_HEADER_LEN],
+                               size_t *count);
+
+struct rs_packet *rs_packet_parse(const struct rs_config *ctx,
+                                 struct rs_packet *packet,
+                                 const uint8_t *buf,
+                                 size_t buflen);
 
 /** Free a packet that has been allocated by @a rs_packet_new().
 
-    @param packet Packet to free.  */
-void rs_packet_free(struct rs_packet *packet);
+    @param packet Packet to free.
+    FIXME
+*/
+void rs_packet_free(const struct rs_config *ctx,
+                   struct rs_packet *packet);
 
 /** Serialize a packet.
 
index 17e089a..f79816c 100644 (file)
@@ -1,10 +1,17 @@
-/** @file libradsec-libevent.h
+/** @file libradsec-levent.h
     @brief API for libradsec-libevent.  */
 
 /* FIXME: License blurb goes here.  */
 
+#include <sys/socket.h>
 #include "libradsec.h"
 
+struct rs_connection {
+    struct rs_config *conf;
+    struct sockaddr_storage addr;
+    char open_flag;
+};
+
 typedef void (*rs_conn_connected_cb)(void *user_data /* FIXME: peer? */);
 typedef void (*rs_conn_disconnected_cb)(void *user_data /* FIXME: reason? */);
 typedef void (*rs_conn_packet_received_cb)(const struct rs_packet *packet,
index 89f9f2f..fd69c58 100644 (file)
@@ -4,14 +4,19 @@
 /* FIXME: License blurb goes here.  */
 
 #include <stdint.h>
-#include <sys/socket.h>
-#include "../list.h"
+#include "../list.h"           /* FIXME: ../ is not very nice */
+
+#define RS_HEADER_LEN 4
+
 
 /* Data types.  */
 
-struct rs_config {
-    /* FIXME: What's in here that's not in struct rs_conn or
-     * rs_credentials?  */;
+enum rs_conn_type {
+    RS_CONN_TYPE_NONE = 0,
+    RS_CONN_TYPE_UDP,
+    RS_CONN_TYPE_TCP,
+    RS_CONN_TYPE_TLS,
+    RS_CONN_TYPE_DTLS,
 };
 
 enum rs_cred_type {
@@ -22,21 +27,24 @@ enum rs_cred_type {
 struct rs_credentials {
     enum rs_cred_type type;
     char *identity;
-    char *secret;              /* Passphrase or PSK.  */
+    char *secret;
 };
 
-enum rs_conn_type {
-    RS_CONN_TYPE_NONE = 0,
-    RS_CONN_TYPE_UDP,
-    RS_CONN_TYPE_TCP,
-    RS_CONN_TYPE_TLS,
-    RS_CONN_TYPE_DTLS,
+typedef void * (*rs_calloc)(size_t nmemb, size_t size);
+typedef void * (*rs_malloc)(size_t size);
+typedef void (*rs_free)(void *ptr);
+typedef void * (*rs_realloc)(void *ptr, size_t size);
+struct rs_alloc_scheme {
+    rs_calloc calloc;
+    rs_malloc malloc;
+    rs_free free;
+    rs_realloc realloc;
 };
-struct rs_conn {
-    enum rs_conn_type type;
+
+struct rs_config {
+    enum rs_conn_type conn_type;
     struct rs_credentials transport_credentials;
-    struct sockaddr_storage addr;
-    char open_flag;
+    struct rs_alloc_scheme alloc_scheme;
 };
 
 struct rs_attribute {
diff --git a/lib/test-blocking.c b/lib/test-blocking.c
new file mode 100644 (file)
index 0000000..641a34f
--- /dev/null
@@ -0,0 +1,62 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "blocking.h"
+
+int
+f (const struct sockaddr *addr,
+   socklen_t addrlen,
+   int out_fd)
+{
+  int fd = -1;
+  //struct rs_alloc_scheme as = { calloc, malloc, free, realloc };
+  struct rs_config ctx = { RS_CONN_TYPE_TCP, RS_CRED_NONE, NULL };
+  struct rs_packet *p = NULL;
+
+  fd = rs_connect (&ctx, addr, addrlen);
+  if (fd < 0)
+    {
+      perror ("rs_connect");
+      return -1;
+    }
+
+  p = next_packet (&ctx, fd);
+  if (p == NULL)
+    {
+      perror ("next_packet");
+      rs_disconnect (&ctx, fd);
+      return -1;
+    }
+  rs_disconnect (&ctx, fd);
+
+  if (send_packet (&ctx, out_fd, p))
+    {
+      rs_packet_free (&ctx, p);
+      perror ("send_packet");
+      return -1;
+    }
+
+    return 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+  struct addrinfo *ai;
+  int rc;
+
+  rc = getaddrinfo (argv[1], argv[2], NULL, &ai);
+  if (rc)
+    {
+      if (rc == EAI_SYSTEM)
+       perror ("getaddrinfo");
+      else
+       fprintf (stderr, "getaddrinfo: %s\n", gai_strerror (rc));
+      return -1;
+    }
+
+  return f (ai->ai_addr, ai->ai_addrlen, 1);
+}