]> git.meshlink.io Git - catta/commitdiff
* Update HACKING
authorLennart Poettering <lennart@poettering.net>
Tue, 9 Aug 2005 00:32:32 +0000 (00:32 +0000)
committerLennart Poettering <lennart@poettering.net>
Tue, 9 Aug 2005 00:32:32 +0000 (00:32 +0000)
* Change DBUS API: txt record lists are now coded as "aay" instead of "as".
  Unfortunately this triggers this bug:

  https://bugs.freedesktop.org/show_bug.cgi?id=4023

  If you want to use avahi-publish-service you need to apply the included patch.

* change avahi-bookmarks to listen on 127.0.0.1 only
* add ftp and https browsing support to avahi-bookmarks, but disable it due to python-dbus bugs
* update avahi module for python to provide functions to convert between tring lists and lists of lists of bytes
* add avahi_strlst_add_anonymous()

git-svn-id: file:///home/lennart/svn/public/avahi/trunk@281 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe

12 files changed:
avahi-common/strlst.c
avahi-common/strlst.h
avahi-daemon/EntryGroup.introspect
avahi-daemon/Server.introspect
avahi-daemon/dbus-protocol.c
avahi-utils/avahi-bookmarks.in
avahi-utils/avahi-browse.in
avahi-utils/avahi-discover.in
avahi-utils/avahi-publish-service.in
avahi-utils/avahi/__init__.py
docs/HACKING
docs/TODO

index d4d67da2d9d3c9250f27034fbe90f454efca5dc4..46ed852720766b5df780c2d75f6f0fa5b7129caf 100644 (file)
 
 #include "strlst.h"
 
+AvahiStringList*avahi_string_list_add_anonymous(AvahiStringList *l, guint size) {
+    AvahiStringList *n;
+
+    n = g_malloc(sizeof(AvahiStringList) + size);
+    n->next = l;
+    n->size = size;
+    
+    return n;
+}
+
 AvahiStringList *avahi_string_list_add_arbitrary(AvahiStringList *l, const guint8*text, guint size) {
     AvahiStringList *n;
 
     g_assert(text);
 
-    n = g_malloc(sizeof(AvahiStringList) + size);
-    n->next = l;
-    memcpy(n->text, text, n->size = size);
+    n = avahi_string_list_add_anonymous(l, size);
+
+    if (size > 0)
+        memcpy(n->text, text, size);
     
     return n;
 }
index 99a9d2aa2b0fb0769fa11ab9dfcf8d22fa89f04f..a4a4202a19c16ca9ca9f1962b3b10b60d85811e9 100644 (file)
@@ -62,10 +62,17 @@ void avahi_string_list_free(AvahiStringList *l);
  * start. */
 AvahiStringList *avahi_string_list_add(AvahiStringList *l, const gchar *text);
 
-/** Append am arbitrary length byte string to the list. Returns the
+/** Append an arbitrary length byte string to the list. Returns the
  * new list start. */
 AvahiStringList *avahi_string_list_add_arbitrary(AvahiStringList *l, const guint8 *text, guint size);
 
+/** Append a new entry to the string list. The string is not filled
+with data. The caller should fill in string data afterwards by writing
+it to l->text, where l is the pointer returned by this function. This
+function exists solely to optimize a few operations where otherwise
+superfluous string copying would be necessary. */
+AvahiStringList*avahi_string_list_add_anonymous(AvahiStringList *l, guint size);
+
 /** Same as avahi_string_list_add(), but takes a variable number of
  * NUL terminated strings. The argument list must be terminated by a
  * NULL pointer. Returns the new list start. */
@@ -99,6 +106,7 @@ AvahiStringList* avahi_string_list_reverse(AvahiStringList *l);
 /** Return the number of elements in the string list */
 guint avahi_string_list_length(const AvahiStringList *l);
 
+
 AVAHI_C_DECL_END
 
 #endif
index a33f338724a7d3dfb0a47468bb48238831dec8b7..40ddf3a380ea1328bb20c295ff6a2c4179b8252e 100644 (file)
@@ -35,7 +35,7 @@
       <arg name="domain" type="s" direction="in"/>
       <arg name="host" type="s" direction="in"/>
       <arg name="port" type="q" direction="in"/>
-      <arg name="txt" type="as" direction="in"/>
+      <arg name="txt" type="aay" direction="in"/>
     </method>
 
     <method name="AddAddress">
index 4fa7d5e13eeeca06ba5b0c42b5411cb6ad2668b2..4a939067b1a5127ca3281d85b7b71278021f79ff 100644 (file)
@@ -94,7 +94,7 @@
       <arg name="aprotocol" type="i" direction="out"/>
       <arg name="address" type="s" direction="out"/>
       <arg name="port" type="q" direction="out"/>
-      <arg name="txt" type="as" direction="out"/>
+      <arg name="txt" type="aay" direction="out"/>
     </method>
 
     <method name="EntryGroupNew">
index 7fe6bf9bba735e532b51eb1b1b3c7207dd7a40d6..3653f4edde06904be92a54f0a88a4363682703d5 100644 (file)
@@ -56,6 +56,8 @@ typedef struct ServiceResolverInfo ServiceResolverInfo;
 #define MAX_OBJECTS_PER_CLIENT 50
 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
 
+#define VALGRIND_WORKAROUND
+
 struct EntryGroupInfo {
     guint id;
     Client *client;
@@ -600,6 +602,8 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
         gchar **txt = NULL;
         gint txt_len;
         AvahiStringList *strlst;
+        DBusMessageIter iter, sub;
+        int j;
         
         if (!dbus_message_get_args(
                 m, &error,
@@ -610,21 +614,53 @@ static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m,
                 DBUS_TYPE_STRING, &domain,
                 DBUS_TYPE_STRING, &host,
                 DBUS_TYPE_UINT16, &port, 
-                DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &txt, &txt_len,
                 DBUS_TYPE_INVALID) || !type || !name) {
             avahi_log_warn("Error parsing EntryGroup::AddService message");
             goto fail;
         }
 
+        dbus_message_iter_init(m, &iter);
+
+        for (j = 0; j < 7; j++)
+            dbus_message_iter_next(&iter);
+        
+        if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
+            dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
+            avahi_log_warn("Error parsing EntryGroup::AddService message 2");
+            goto fail;
+        }
+
+        strlst = NULL;
+        dbus_message_iter_recurse(&iter, &sub);
+        
+        for (;;) {
+            DBusMessageIter sub2;
+            int at, n;
+            guint8 *k;
+
+            if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
+                break;
+
+            g_assert(at == DBUS_TYPE_ARRAY);
+            
+            if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
+                avahi_log_warn("Error parsing EntryGroup::AddService message");
+                goto fail;
+            }
+
+            dbus_message_iter_recurse(&sub, &sub2);
+            dbus_message_iter_get_fixed_array(&sub2, &k, &n);
+            strlst = avahi_string_list_add_arbitrary(strlst, k, n);
+            
+            dbus_message_iter_next(&sub);
+        }
+
         if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
+            avahi_string_list_free(strlst);
             avahi_log_warn("Too many entries per entry group, client request failed.");
-            dbus_free_string_array(txt);
             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
         }
 
-        strlst = avahi_string_list_new_from_array((const gchar**) txt, txt_len);
-        dbus_free_string_array(txt);
-
         if (domain && !*domain)
             domain = NULL;
 
@@ -994,10 +1030,10 @@ static void service_resolver_callback(
     if (event == AVAHI_RESOLVER_FOUND) {
         char t[256], *pt = t;
         gint32 i_interface, i_protocol, i_aprotocol;
-        gchar **array;
         guint n, j;
         AvahiStringList *p;
         DBusMessage *reply;
+        DBusMessageIter iter, sub;
 
         g_assert(host_name);
         
@@ -1008,12 +1044,6 @@ static void service_resolver_callback(
         i_protocol = (gint32) protocol;
         i_aprotocol = (gint32) a->family;
 
-        array = g_new(gchar*, (n = avahi_string_list_length(txt)));
-
-        /** FIXME: DBUS doesn't support strings that include NUL bytes (?) */
-        for (p = txt, j = n-1; p; p = p->next, j--)
-            array[j] = g_strndup((gchar*) p->text, p->size);
-        
         reply = dbus_message_new_method_return(i->message);
         dbus_message_append_args(
             reply,
@@ -1026,12 +1056,22 @@ static void service_resolver_callback(
             DBUS_TYPE_INT32, &i_aprotocol,
             DBUS_TYPE_STRING, &pt,
             DBUS_TYPE_UINT16, &port,
-            DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &array, n,
             DBUS_TYPE_INVALID);
 
-        for (j = 0; j < n; j++)
-            g_free(array[j]);
+        dbus_message_iter_init_append(reply, &iter);
+        dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
+
+        for (p = txt, j = n-1; p; p = p->next, j--) {
+            DBusMessageIter sub2;
+            const guint8 *data = p->text;
+            
+            dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
+            dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size); 
+            dbus_message_iter_close_container(&sub, &sub2);
 
+        }
+        dbus_message_iter_close_container(&iter, &sub);
+                
         dbus_connection_send(server->bus, reply, NULL);
         dbus_message_unref(reply);
     } else {
@@ -1111,6 +1151,10 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             goto fail;
         }
 
+#ifdef VALGRIND_WORKAROUND
+        return respond_string(c, m, "blah");
+#else
+        
         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
             gchar txt[256];
             g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
@@ -1130,7 +1174,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         close(fd);
         
         return respond_string(c, m, ifr.ifr_name);
-
+#endif
+        
     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
         gchar *n;
         int fd;
@@ -1141,6 +1186,9 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
             goto fail;
         }
 
+#ifdef VALGRIND_WORKAROUND
+        return respond_int32(c, m, 1);
+#else
         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
             gchar txt[256];
             g_snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
@@ -1160,6 +1208,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void
         close(fd);
         
         return respond_int32(c, m, ifr.ifr_ifindex);
+#endif
 
     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
         gchar *n, * t;
index 72f8e44981b945c0242ed4020771713721b621d0..953020a5978f93a825931e602dadef89eb5de815 100755 (executable)
@@ -41,6 +41,8 @@ except ImportError:
     print "Sorry, to use this tool you need to install twisted."
     sys.exit(1)
 
+urlproto = { "_http._tcp" : "http",  "_https._tcp" : "https", "_ftp._tcp" : "ftp" }
+
 class AvahiBookmarks(resource.Resource):
     isLeaf = True
 
@@ -49,20 +51,28 @@ class AvahiBookmarks(resource.Resource):
     def __init__(self):
         resource.Resource.__init__(self)
 
-
         self.bus = dbus.SystemBus()
         self.server = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, avahi.DBUS_PATH_SERVER), avahi.DBUS_INTERFACE_SERVER)
 
         self.version_string = self.server.GetVersionString()
 
-        self.browser = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, "_http._tcp", "local")), avahi.DBUS_INTERFACE_SERVICE_BROWSER)
+        self.browse_service_type("_http._tcp")
+
+        # Hurrah! if I enable one of the following lines, python segfaults.
+        #self.browse_service_type("_shttp._tcp")
+        #self.browse_service_type("_ftp._tcp")
 
-        self.browser.connect_to_signal('ItemNew', self.new_service)
-        self.browser.connect_to_signal('ItemRemove', self.remove_service)
+    def browse_service_type(self, stype):
+
+        browser = dbus.Interface(self.bus.get_object(avahi.DBUS_NAME, self.server.ServiceBrowserNew(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, stype, "local")), avahi.DBUS_INTERFACE_SERVICE_BROWSER)
+        browser.connect_to_signal('ItemNew', self.new_service)
+        browser.connect_to_signal('ItemRemove', self.remove_service)
 
     def find_path(self, txt):
 
-        for k in txt:
+        l = avahi.txt_array_to_string_array(txt)
+
+        for k in l:
             if k[:5] == "path=":
                 return k[5:]
 
@@ -86,8 +96,7 @@ class AvahiBookmarks(resource.Resource):
 
                 path = self.find_path(v[4])
 
-
-                t += '<li><a href="http://%s%s%s">%s</a></li>' % (v[2], port, path, k[2])
+                t += '<li><a href="%s://%s%s%s">%s</a></li>' % (urlproto[k[3]], v[2], port, path, k[2])
                 
             t += '</ul>'
         
@@ -110,7 +119,7 @@ port = 8080
 
 if __name__ == '__main__':
     site = server.Site(AvahiBookmarks())
-    reactor.listenTCP(port, site)
+    reactor.listenTCP(port, site, interface="127.0.0.1")
 
     print "Now point your web browser to http://localhost:%u/!" % port
 
index 69a8bfdeb5cc285c49bb552546f1fd66ff549209..3507b417f10467f7f228d1b9ad7ce925ec598b09 100755 (executable)
@@ -80,7 +80,7 @@ def siocgifname(interface):
 
 def service_resolved(interface, protocol, name, type, domain, host, aprotocol, address, port, txt):
     print "Service data for service '%s' of type '%s' in domain '%s' on %s.%i:" % (name, type, domain, siocgifname(interface), protocol)
-    print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(txt))
+    print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, avahi.txt_array_to_string_array(txt))
 
 def print_error(err):
     print "Error:", str(err)
index 6c78c51ef7bde047fcbf20423a7c6728f3ce08f9..d8697616f8434386df20e3006cd928c72ced58b1 100755 (executable)
@@ -68,8 +68,8 @@ class Main_window(SimpleGladeApp):
                         
     def service_resolved(self, interface, protocol, name, type, domain, host, aprotocol, address, port, txt):
         print "Service data for service '%s' of type '%s' in domain '%s' on %i.%i:" % (name, type, domain, interface, protocol)
-        print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(txt))
-        self.update_label(interface, protocol, name, type, domain, host, aprotocol, address, port, str(txt))
+        print "\tHost %s (%s), port %i, TXT data: %s" % (host, address, port, str(avahi.txt_array_to_string_array(txt)))
+        self.update_label(interface, protocol, name, type, domain, host, aprotocol, address, port, str(avahi.txt_array_to_string_array(txt)))
         
     def print_error(err):
         print "Error:", str(err)
index 50b1908c2660f5af9e6d90654323cad6284639c3..0f278eba66a09ac9b54205157191513f500a5132 100755 (executable)
@@ -88,7 +88,8 @@ def add_service():
 
     print "Adding service '%s' of type '%s' ..." % (name, stype)
     group.connect_to_signal('StateChanged', entry_group_state_changed)
-    group.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, name, stype, domain, host, dbus.UInt16(port), txt)
+
+    group.AddService(avahi.IF_UNSPEC, avahi.PROTO_UNSPEC, name, stype, domain, host, dbus.UInt16(port), avahi.string_array_to_txt_array(txt))
     group.Commit()
 
 def entry_group_state_changed(state):
index c68e1770ab92fa72a95cc3428c17b57943e92462..90d2b7639aba5578920399a3f93246ff75eb3094 100644 (file)
@@ -18,7 +18,7 @@
 # USA.
 
 # Some definitions matching those in core.h
-import socket
+import socket, dbus
 
 SERVER_INVALID, SERVER_REGISTERING, SERVER_RUNNING, SERVER_COLLISION = range(-1, 3)
 
@@ -37,3 +37,40 @@ DBUS_INTERFACE_ENTRY_GROUP = DBUS_NAME + ".EntryGroup"
 DBUS_INTERFACE_DOMAIN_BROWSER = DBUS_NAME + ".DomainBrowser"
 DBUS_INTERFACE_SERVICE_TYPE_BROWSER = DBUS_NAME + ".ServiceTypeBrowser"
 DBUS_INTERFACE_SERVICE_BROWSER = DBUS_NAME + ".ServiceBrowser"
+
+def byte_array_to_string(s):
+    r = ""
+    
+    for c in s:
+        
+        if c >= 32 and c < 127:
+            r += "%c" % c
+        else:
+            r += "."
+
+    return r
+
+def txt_array_to_string_array(t):
+    l = []
+
+    for s in t:
+        l.append(byte_array_to_string(s))
+
+    return l
+
+
+def string_to_byte_array(s):
+    r = []
+
+    for c in s:
+        r.append(dbus.Byte(ord(c)))
+
+    return r
+
+def string_array_to_txt_array(t):
+    l = []
+
+    for s in t:
+        l.append(string_to_byte_array(s))
+
+    return l
index a31878d0d498f4a8af04c53cf5edb16a7b2db9b8..46504da55ab58f4163be78e5064f58c4e6ee73c5 100644 (file)
@@ -25,6 +25,17 @@ Please comply with the following rules when hacking on Avahi:
 
  * Never forget that Avahi should be buildable without DBUS, GTK or python!
 
+ * Before commiting, test your code! In case of C consider running it
+   a few times through valgrind, to make sure that you got everything
+   right.  You have to call libtool explicitly when running valgrind
+   on binaries that depend on shared objects. e.g:
+
+       libtool --mode=execute valgrind ./avahi-daemon
+
+   Please note that valgrind can't find you all bugs. Please check
+   your code thrice with your brain before committing. Valgrind is
+   only a final check.
+
  * When you code in C, please compile with the following gcc options from time
    to time:
   
index ba9a14a6ce27703d4b5d51de38978fcd86e74a26..5ce60ce5f90cbe070e2c2141db5abbdec27aa131 100644 (file)
--- a/docs/TODO
+++ b/docs/TODO
@@ -1,6 +1,4 @@
 todo:
-* finish DBUS stuff:
-       - allow NUL bytes in TXT records
 * release!
 
 later:
@@ -49,3 +47,4 @@ done:
 * drop trailing dot on avahi_normalize_name()
 * add entry_group::reset()
 * add internal error codes
+* finish DBUS stuff: allow NUL bytes in TXT records