]> git.meshlink.io Git - catta/blobdiff - rr.c
* Complete conflict detection stuff (including probing et al)
[catta] / rr.c
diff --git a/rr.c b/rr.c
index f72557b055ebf01101a00707cfad7c3cc5d82ff8..49a60b44313e2d915768ff961e9c58182418ae94 100644 (file)
--- a/rr.c
+++ b/rr.c
@@ -6,6 +6,7 @@
 
 #include "util.h"
 #include "rr.h"
+#include "dns.h"
 
 flxKey *flx_key_new(const gchar *name, guint16 class, guint16 type) {
     flxKey *k;
@@ -163,7 +164,7 @@ gchar *flx_key_to_string(const flxKey *k) {
 
 gchar *flx_record_to_string(const flxRecord *r) {
     gchar *p, *s;
-    char buf[257], *t, *d = NULL;
+    char buf[257], *t = NULL, *d = NULL;
 
     switch (r->key->type) {
         case FLX_DNS_TYPE_A:
@@ -214,7 +215,7 @@ gboolean flx_key_equal(const flxKey *a, const flxKey *b) {
 
 /*     g_message("equal: %p %p", a, b); */
     
-    return strcmp(a->name, b->name) == 0 &&
+    return flx_domain_equal(a->name, b->name) &&
         a->type == b->type &&
         a->class == b->class;
 }
@@ -227,7 +228,7 @@ gboolean flx_key_pattern_match(const flxKey *pattern, const flxKey *k) {
 
     g_assert(!flx_key_is_pattern(k));
     
-    return strcmp(pattern->name, k->name) == 0 &&
+    return flx_domain_equal(pattern->name, k->name) &&
         (pattern->type == k->type || pattern->type == FLX_DNS_TYPE_ANY) &&
         pattern->class == k->class;
 }
@@ -242,7 +243,7 @@ gboolean flx_key_is_pattern(const flxKey *k) {
 guint flx_key_hash(const flxKey *k) {
     g_assert(k);
 
-    return g_str_hash(k->name) + k->type + k->class;
+    return flx_domain_hash(k->name) + k->type + k->class;
 }
 
 static gboolean rdata_equal(const flxRecord *a, const flxRecord *b) {
@@ -265,11 +266,11 @@ static gboolean rdata_equal(const flxRecord *a, const flxRecord *b) {
                 a->data.srv.priority == b->data.srv.priority &&
                 a->data.srv.weight == b->data.srv.weight &&
                 a->data.srv.port == b->data.srv.port &&
-                !strcmp(a->data.srv.name, b->data.srv.name);
+                flx_domain_equal(a->data.srv.name, b->data.srv.name);
 
         case FLX_DNS_TYPE_PTR:
         case FLX_DNS_TYPE_CNAME:
-            return !strcmp(a->data.ptr.name, b->data.ptr.name);
+            return flx_domain_equal(a->data.ptr.name, b->data.ptr.name);
 
         case FLX_DNS_TYPE_HINFO:
             return
@@ -395,3 +396,139 @@ guint flx_record_get_estimate_size(flxRecord *r) {
 
     return n;
 }
+
+static gint lexicographical_memcmp(gconstpointer a, size_t al, gconstpointer b, size_t bl) {
+    size_t c;
+    gint ret;
+    
+    g_assert(a);
+    g_assert(b);
+
+    c = al < bl ? al : bl;
+    if ((ret = memcmp(a, b, c)) != 0)
+        return ret;
+
+    if (al == bl)
+        return 0;
+    else
+        return al == c ? 1 : -1;
+}
+
+static gint uint16_cmp(guint16 a, guint16 b) {
+    return a == b ? 0 : (a < b ? a : b);
+}
+
+static gint lexicographical_domain_cmp(const gchar *a, const gchar *b) {
+    g_assert(a);
+    g_assert(b);
+    
+
+    for (;;) {
+        gchar t1[64];
+        gchar t2[64];
+        size_t al, bl;
+        gint r;
+
+        if (!a && !b)
+            return 0;
+
+        if (a && !b)
+            return 1;
+
+        if (b && !a)
+            return -1;
+        
+        flx_unescape_label(t1, sizeof(t1), &a);
+        flx_unescape_label(t2, sizeof(t2), &b);
+
+        al = strlen(t1);
+        bl = strlen(t2);
+        
+        if (al != bl) 
+            return al < bl ? -1 : 1;
+
+        if ((r =  strcmp(t1, t2)) != 0)
+            return r;
+    }
+}
+
+gint flx_record_lexicographical_compare(flxRecord *a, flxRecord *b) {
+    g_assert(a);
+    g_assert(b);
+
+    if (a->key->class < b->key->class)
+        return -1;
+    else if (a->key->class > b->key->class)
+        return 1;
+
+    if (a->key->type < b->key->type)
+        return -1;
+    else if (a->key->type > b->key->type)
+        return 1;
+
+    switch (a->key->type) {
+
+        case FLX_DNS_TYPE_PTR:
+        case FLX_DNS_TYPE_CNAME:
+            return lexicographical_domain_cmp(a->data.ptr.name, b->data.ptr.name);
+
+        case FLX_DNS_TYPE_SRV: {
+            gint r;
+            if ((r = uint16_cmp(a->data.srv.priority, b->data.srv.priority)) != 0 ||
+                (r = uint16_cmp(a->data.srv.weight, b->data.srv.weight)) != 0 ||
+                (r = uint16_cmp(a->data.srv.port, b->data.srv.port)) != 0)
+                return lexicographical_domain_cmp(a->data.srv.name, b->data.srv.name);
+        }
+
+        case FLX_DNS_TYPE_HINFO: {
+            size_t al = strlen(a->data.hinfo.cpu), bl = strlen(b->data.hinfo.cpu);
+            gint r;
+
+            if (al != bl)
+                return al < bl ? -1 : 1;
+
+            if ((r = strcmp(a->data.hinfo.cpu, b->data.hinfo.cpu)) != 0)
+                return r;
+
+            al = strlen(a->data.hinfo.os), bl = strlen(b->data.hinfo.os);
+
+            if (al != bl)
+                return al < bl ? -1 : 1;
+
+            if ((r = strcmp(a->data.hinfo.os, b->data.hinfo.os)) != 0)
+                return r;
+
+            return 0;
+
+        }
+
+        case FLX_DNS_TYPE_TXT: {
+
+            guint8 *ma, *mb;
+            guint asize, bsize;
+            gint r;
+
+            ma = g_new(guint8, asize = flx_string_list_serialize(a->data.txt.string_list, NULL, 0));
+            mb = g_new(guint8, bsize = flx_string_list_serialize(b->data.txt.string_list, NULL, 0));
+            flx_string_list_serialize(a->data.txt.string_list, ma, asize);
+            flx_string_list_serialize(a->data.txt.string_list, mb, bsize);
+
+            r = lexicographical_memcmp(ma, asize, mb, bsize);
+            g_free(ma);
+            g_free(mb);
+
+            return r;
+        }
+        
+        case FLX_DNS_TYPE_A:
+            return memcmp(&a->data.a.address, &b->data.a.address, sizeof(flxIPv4Address));
+
+        case FLX_DNS_TYPE_AAAA:
+            return memcmp(&a->data.aaaa.address, &b->data.aaaa.address, sizeof(flxIPv6Address));
+
+        default:
+            return lexicographical_memcmp(a->data.generic.data, a->data.generic.size,
+                                          b->data.generic.data, b->data.generic.size);
+    }
+    
+}