<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>rbtree.c</filename>
    </added>
    <added>
      <filename>rbtree.h</filename>
    </added>
    <added>
      <filename>test_rbtree.c</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -6,11 +6,14 @@ GCC_OPTS  = -fPIC -g -Wall
 #libebb.so.0.0.1: objects
 #	gcc -shared -Wl,-soname,libebb.so.0 -o $@ ebb.o ebb_request_parser.o
 
-objects: ebb.o ebb_request_parser.o 
+objects: ebb.o ebb_request_parser.o rbtree.o
 
 ebb.o: ebb.c ebb.h
 	gcc ${CFLAGS} -c $&lt; -o $@
 
+rbtree.o: rbtree.c rbtree.h
+	gcc ${CFLAGS} -c $&lt; -o $@
+
 ebb_request_parser.o: ebb_request_parser.c ebb_request_parser.h
 	gcc ${CFLAGS} -c $&lt; -o $@
 
@@ -20,9 +23,12 @@ ebb_request_parser.c: ebb_request_parser.rl
 test_request_parser: test_request_parser.c ebb_request_parser.o
 	gcc ${CFLAGS} -lefence  $^ -o $@
 
+test_rbtree: test_rbtree.c rbtree.o
+	gcc ${CFLAGS} -lefence  $^ -o $@
+
 examples: examples/hello_world
 
-examples/hello_world: examples/hello_world.c ebb.o ebb_request_parser.o
+examples/hello_world: examples/hello_world.c ebb.o ebb_request_parser.o rbtree.o
 	gcc ${CFLAGS} ${LIBS} -lefence $^ -o $@
 
 .PHONY: clean test clobber
@@ -30,16 +36,17 @@ examples/hello_world: examples/hello_world.c ebb.o ebb_request_parser.o
 wc:
 	wc -l ebb_request_parser.rl ebb_request_parser.h ebb.c ebb.h test_*.c
 
-test: test_request_parser
+test: test_request_parser test_rbtree
 	./test_request_parser
+	./test_rbtree
 
 upload_website:
 	scp -r doc/index.html doc/icon.png rydahl@tinyclouds.org:~/web/public/libebb
 
-
 clean:
 	@-rm -f *.o
 	@-rm -f test_request_parser
+	@-rm -f test_rbtree
 	@-rm -f examples/hello_world
 	@-rm -f libebb.so.0.0.1
 	</diff>
      <filename>Makefile</filename>
    </modified>
    <modified>
      <diff>@@ -4,7 +4,7 @@ webpage: http://tinyclouds.org/libebb/
 git repository: http://github.com/ry/libebb/tree/master
 
 (The MIT) LICENSE
-Copyright &#169; 2008 [Ryah Dahl](http://tinyclouds.org) (ry at tiny clouds dot org)
+Copyright &#169; 2008 Ryah Dahl (ry@tinyclouds.org)
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the</diff>
      <filename>README</filename>
    </modified>
    <modified>
      <diff>@@ -22,10 +22,12 @@
 #include &lt;gnutls/gnutls.h&gt;
 
 #include &quot;ebb.h&quot;
+#include &quot;rbtree.h&quot;
 #include &quot;ebb_request_parser.h&quot;
 
 #define TRUE 1
 #define FALSE 0
+#define MIN(a,b) (a &lt; b ? a : b)
 
 #define FREE_CONNECTION_IF_CLOSED \
   if(!connection-&gt;open &amp;&amp; connection-&gt;free) connection-&gt;free(connection);
@@ -34,6 +36,108 @@
 #define GNUTLS_NEED_READ (gnutls_record_get_direction(connection-&gt;session) == 0)
 #define CONNECTION_HAS_SOMETHING_TO_WRITE (connection-&gt;to_write != NULL)
 
+
+#define EBB_MAX_SESSION_ID_SIZE 32
+#define EBB_MAX_SESSION_DATA_SIZE 512
+
+struct session_cache {
+  struct rbtree_node_t node;
+
+  gnutls_datum_t key;
+  gnutls_datum_t value;
+
+  char key_storage[EBB_MAX_SESSION_ID_SIZE];
+  char value_storage[EBB_MAX_SESSION_DATA_SIZE];
+};
+
+static int session_cache_compare (void *left, void *right) {
+  gnutls_datum_t *left_key = left;
+  gnutls_datum_t *right_key = right;
+  if(left_key-&gt;size &lt; right_key-&gt;size)
+    return -1;
+  else if(left_key-&gt;size &gt; right_key-&gt;size)
+    return 1;
+  else
+    return memcmp( left_key-&gt;data
+                 , right_key-&gt;data
+                 , MIN(left_key-&gt;size, right_key-&gt;size)
+                 );
+}
+
+static int
+session_cache_store(void *data, gnutls_datum_t key, gnutls_datum_t value)
+{
+  rbtree tree = data;
+
+  if( tree == NULL
+   || key.size &gt; EBB_MAX_SESSION_ID_SIZE
+   || value.size &gt; EBB_MAX_SESSION_DATA_SIZE
+    ) return -1;
+
+  struct session_cache *cache = gnutls_malloc(sizeof(struct session_cache));
+
+  memcpy (cache-&gt;key_storage, key.data, key.size);
+  cache-&gt;key.size = key.size;
+  cache-&gt;key.data = (void*)cache-&gt;key_storage;
+
+  memcpy (cache-&gt;value_storage, value.data, value.size);
+  cache-&gt;value.size = value.size;
+  cache-&gt;value.data = (void*)cache-&gt;value_storage;
+
+  cache-&gt;node.key = &amp;cache-&gt;key;
+  cache-&gt;node.value = &amp;cache;
+
+  rbtree_insert(tree, (rbtree_node)cache);
+
+  //printf(&quot;session_cache_store\n&quot;);
+
+  return 0;
+}
+
+static gnutls_datum_t
+session_cache_retrieve (void *data, gnutls_datum_t key)
+{
+  rbtree tree = data;
+  gnutls_datum_t res = { NULL, 0 };
+  struct session_cache *cache = rbtree_lookup(tree, &amp;key);
+
+  if(cache == NULL)
+    return res;
+
+  res.size = cache-&gt;value.size;
+  res.data = gnutls_malloc (res.size);
+  if(res.data == NULL)
+    return res;
+
+  memcpy(res.data, cache-&gt;value.data, res.size);
+
+  //printf(&quot;session_cache_retrieve\n&quot;);
+
+  return res;
+}
+
+static int
+session_cache_remove (void *data, gnutls_datum_t key)
+{
+  rbtree tree = data;
+
+  if(tree == NULL)
+    return -1;
+
+  struct session_cache *cache = (struct session_cache *)rbtree_delete(tree, &amp;key);
+  if(cache == NULL)
+    return -1;
+
+  gnutls_free(cache);
+
+  //printf(&quot;session_cache_remove\n&quot;);
+
+  return 0;
+}
+
+
+
+
 static void set_nonblock (int fd)
 {
   int flags = fcntl(fd, F_GETFL, 0);
@@ -282,6 +386,11 @@ static void on_connection(struct ev_loop *loop, ev_io *watcher, int revents)
     gnutls_transport_set_ptr(connection-&gt;session, (gnutls_transport_ptr) connection); 
     gnutls_transport_set_push_function(connection-&gt;session, push);
     gnutls_transport_set_pull_function(connection-&gt;session, pull);
+
+    gnutls_db_set_ptr (connection-&gt;session, &amp;server-&gt;session_cache);
+    gnutls_db_set_store_function (connection-&gt;session, session_cache_store);
+    gnutls_db_set_retrieve_function (connection-&gt;session, session_cache_retrieve);
+    gnutls_db_set_remove_function (connection-&gt;session, session_cache_remove);
   }
 
   ev_io_set(&amp;connection-&gt;handshake_watcher, connection-&gt;fd, EV_READ | EV_WRITE | EV_ERROR);
@@ -415,6 +524,8 @@ void ebb_server_init(ebb_server *server, struct ev_loop *loop)
  * GNUTLS. In particular 
  * gnutls_global_set_mem_functions() 
  * gnutls_global_set_log_function()
+ * Also see the note above ebb_connection_init() about setting gnutls cache
+ * access functions
  *
  * cert_file: the filename of a PEM certificate file
  *
@@ -435,6 +546,9 @@ void ebb_secure_server_init(ebb_server *server, struct ev_loop *loop,
                                               , GNUTLS_X509_FMT_PEM
                                               );
   assert(r &gt;= 0 &amp;&amp; &quot;error loading certificates&quot;);
+
+
+  rbtree_init(&amp;server-&gt;session_cache, session_cache_compare);
 }
 
 static ebb_buf* default_new_buf(ebb_connection *connection)
@@ -464,6 +578,14 @@ static ebb_request* new_request_wrapper(void *data)
  * ebb_connection structure. Most likely, this will only be called within
  * the ebb_server-&gt;new_connection callback which you supply. 
  *
+ * If using SSL do consider setting
+ *   gnutls_db_set_retrieve_function (connection-&gt;session, _);
+ *   gnutls_db_set_remove_function (connection-&gt;session, _);
+ *   gnutls_db_set_store_function (connection-&gt;session, _);
+ *   gnutls_db_set_ptr (connection-&gt;session, _);
+ * To provide a better means of storing SSL session caches. libebb provides
+ * only a simple default implementation. 
+ *
  * @param connection the connection to initialize
  * @param timeout    the timeout in seconds
  */</diff>
      <filename>ebb.c</filename>
    </modified>
    <modified>
      <diff>@@ -8,6 +8,7 @@
 #define server_h
 
 #include &quot;ebb_request_parser.h&quot;
+#include &quot;rbtree.h&quot;
 #include &lt;ev.h&gt;
 #include &lt;gnutls/gnutls.h&gt;
 #include &lt;sys/socket.h&gt;
@@ -40,6 +41,7 @@ struct ebb_server {
   unsigned listening:1;                         /* ro */
   unsigned secure:1;                            /* ro */
   gnutls_certificate_credentials_t credentials; /* private */
+  struct rbtree_t session_cache;                /* private */
   ev_io connection_watcher;                     /* private */
 
   /* Public */</diff>
      <filename>ebb.h</filename>
    </modified>
    <modified>
      <diff>@@ -11,8 +11,6 @@
 
 #include &lt;stdio.h&gt;
 #include &lt;assert.h&gt;
-#include &lt;string.h&gt;
-#include &lt;stdlib.h&gt; /* for the default methods */
 
 #define TRUE 1
 #define FALSE 0</diff>
      <filename>ebb_request_parser.rl</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>ead7f8a062838dc69b41aa0aa77a10a77f5c33b4</id>
    </parent>
  </parents>
  <author>
    <name>Ryan</name>
    <email>ry@tinyclouds.org</email>
  </author>
  <url>http://github.com/ry/libebb/commit/82d92c4edfa253e181ae674cbc4d452568d375f1</url>
  <id>82d92c4edfa253e181ae674cbc4d452568d375f1</id>
  <committed-date>2008-07-27T06:28:27-07:00</committed-date>
  <authored-date>2008-07-27T06:26:10-07:00</authored-date>
  <message>Add SSL session storage.</message>
  <tree>447b9c5c863a3d1af4e0fa5a41307ce017cbdc3b</tree>
  <committer>
    <name>Ryan</name>
    <email>ry@tinyclouds.org</email>
  </committer>
</commit>
