ekiga r6738 - trunk/lib/engine/components/avahi-publisher



Author: jpuydt
Date: Sun Aug 31 08:16:05 2008
New Revision: 6738
URL: http://svn.gnome.org/viewvc/ekiga?rev=6738&view=rev

Log:
Rewrote the avahi publisher so it works better

Modified:
   trunk/lib/engine/components/avahi-publisher/avahi-publisher-main.cpp
   trunk/lib/engine/components/avahi-publisher/avahi-publisher.cpp
   trunk/lib/engine/components/avahi-publisher/avahi-publisher.h

Modified: trunk/lib/engine/components/avahi-publisher/avahi-publisher-main.cpp
==============================================================================
--- trunk/lib/engine/components/avahi-publisher/avahi-publisher-main.cpp	(original)
+++ trunk/lib/engine/components/avahi-publisher/avahi-publisher-main.cpp	Sun Aug 31 08:16:05 2008
@@ -47,14 +47,22 @@
 {
   bool result = false;
   Ekiga::PresenceCore* presence_core = NULL;
+  Ekiga::CallCore* call_core = NULL;
+  Ekiga::PersonalDetails* details = NULL;
 
   presence_core
     = dynamic_cast<Ekiga::PresenceCore*>(core.get ("presence-core"));
+  call_core
+    = dynamic_cast<Ekiga::CallCore*>(core.get ("call-core"));
+  details
+    = dynamic_cast<Ekiga::PersonalDetails*>(core.get ("personal-details"));
 
-  if (presence_core != NULL) {
+  if (presence_core != NULL
+      && call_core != NULL
+      && details != NULL) {
 
     Avahi::PresencePublisher* publisher = NULL;
-    publisher = new Avahi::PresencePublisher (core);
+    publisher = new Avahi::PresencePublisher (core, *details, *call_core);
     presence_core->add_presence_publisher (*publisher);
     core.add (*publisher);
     result = true;

Modified: trunk/lib/engine/components/avahi-publisher/avahi-publisher.cpp
==============================================================================
--- trunk/lib/engine/components/avahi-publisher/avahi-publisher.cpp	(original)
+++ trunk/lib/engine/components/avahi-publisher/avahi-publisher.cpp	Sun Aug 31 08:16:05 2008
@@ -1,6 +1,6 @@
 
 /* Ekiga -- A VoIP and Video-Conferencing application
- * Copyright (C) 2000-2006 Damien Sandras
+ * Copyright (C) 2000-2008 Damien Sandras
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,269 +27,261 @@
 
 
 /*
- *                         avahi_publish.cpp  -  description
+ *                         avahi-publisher.cpp  -  description
  *                         ------------------------------------
- *   begin                : Sun Aug 21 2005
- *   copyright            : (C) 2005 by Sebastien Estienne 
- *                          (C) 2008 by Damien Sandras
- *   description          : This file contains the Avahi zeroconf publisher. 
+ *   begin                : Sat Aug 30 2008
+ *   copyright            : (C) 2008 by Julien Puydt
+ *   description          : Avahi publisher implementation
  *
  */
 
-
-#include <iostream>
-#include <sstream>
-
 #include "config.h"
 
 #include "avahi-publisher.h"
-#include "personal-details.h"
 
-#include "call-core.h"
-#include "call-manager.h"
+/* here are the avahi C callbacks */
 
-using namespace Avahi;
+static void
+client_cb (AvahiClient* client,
+	   AvahiClientState state,
+	   Avahi::PresencePublisher* publisher)
+{
+  publisher->client_callback (client, state);
+}
 
+static void
+entry_group_cb (AvahiEntryGroup* group,
+		AvahiEntryGroupState state,
+		Avahi::PresencePublisher* publisher)
+{
+  publisher->entry_group_callback (group, state);
+}
 
-/* Glib callback */
-static gboolean on_disconnect (gpointer data);
+/* here is the real code of the Avahi::PresencePublisher implementation */
 
+Avahi::PresencePublisher::PresencePublisher (Ekiga::ServiceCore& core_,
+					     Ekiga::PersonalDetails& details_,
+					     Ekiga::CallCore& call_core_):
+  core(core_), details(details_), call_core(call_core_),
+  client(NULL), group(NULL)
+{
+  name = avahi_strdup (PACKAGE_NAME " " PACKAGE_VERSION);
+  glib_poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
+  create_client ();
+}
 
-/* Avahi callbacks */
-static void avahi_client_callback (AvahiClient *client, 
-                                   AvahiClientState state, 
-                                   void *data); 
+Avahi::PresencePublisher::~PresencePublisher ()
+{
+  free_client ();
 
-static void avahi_entry_group_callback (AvahiEntryGroup *group, 
-                                        AvahiEntryGroupState state, 
-                                        void *data);
+  avahi_glib_poll_free (glib_poll);
 
+  avahi_free (name);
+}
 
-/* Implementation of the callbacks */
-static gboolean
-on_disconnect (gpointer data)
+void
+Avahi::PresencePublisher::publish (G_GNUC_UNUSED const Ekiga::PersonalDetails& details_)
 {
-  if (data != NULL)
-    ((PresencePublisher *) data)->disconnect ();
-  
-  return FALSE;
-}
+  if (group != NULL) {
 
+    Ekiga::CallManager::InterfaceList interfaces;
+    AvahiStringList* txt_record = NULL;
+    int ret;
+
+    txt_record = prepare_txt_record ();
+    for (Ekiga::CallCore::const_iterator iter = call_core.begin ();
+	 iter != call_core.end ();
+	 ++iter) {
 
-static void 
-avahi_client_callback (AvahiClient *client,
-                       AvahiClientState state, 
-                       void *data) 
-{
-  if (data != NULL)
-    ((PresencePublisher *) data)->client_callback (client, state);
-}
+      Ekiga::CallManager::InterfaceList ints = (*iter)->get_interfaces ();
+      interfaces.insert (interfaces.begin (), ints.begin (), ints.end ());
 
+    }
 
-static void 
-avahi_entry_group_callback (AvahiEntryGroup *group, 
-                            AvahiEntryGroupState state, 
-                            void *data) 
-{
-  if (data != NULL)
-    ((PresencePublisher *) data)->entry_group_callback (group, state);
-}
+    for (Ekiga::CallManager::InterfaceList::const_iterator iter = interfaces.begin ();
+	 iter != interfaces.end ();
+	 ++iter) {
+
+      gchar *typ = NULL;
+
+      typ = g_strdup_printf ("_%s._%s",
+			     iter->voip_protocol.c_str (),
+			     iter->protocol.c_str ());
+
+      /* FIXME: no collision checking here */
+      avahi_entry_group_update_service_txt_strlst (group, AVAHI_IF_UNSPEC,
+						   AVAHI_PROTO_UNSPEC,
+						   (AvahiPublishFlags)0,
+						   name, typ, NULL,
+						   txt_record);
 
+    }
 
+    avahi_string_list_free (txt_record);
+    ret = avahi_entry_group_commit (group);
+  }
+}
 
-/* Implementation of the class */
-PresencePublisher::PresencePublisher (Ekiga::ServiceCore & _core)
-: core (_core)
+void
+Avahi::PresencePublisher::create_client ()
 {
-  /* Create the GLIB Adaptor */
-  glib_poll = avahi_glib_poll_new (NULL, G_PRIORITY_DEFAULT);
-  poll_api = avahi_glib_poll_get (glib_poll);
-  
-  name = NULL;
-  client = NULL;
-  group = NULL;
-  text_record = NULL;
+  free_client ();
+  // don't get the client there : wait what we'll get from the callback
+  avahi_client_new (avahi_glib_poll_get (glib_poll), AVAHI_CLIENT_NO_FAIL,
+		    (AvahiClientCallback)client_cb, this, NULL);
 }
 
-
-PresencePublisher::~PresencePublisher()
+void
+Avahi::PresencePublisher::free_client ()
 {
-  if (text_record) {
-    avahi_string_list_free (text_record);
-    text_record = NULL;
-  }
+  if (client != NULL) {
 
-  if (group) {
-    avahi_entry_group_free (group);
-    group = NULL;
-  }
-  
-  if (client) {
     avahi_client_free (client);
     client = NULL;
   }
-  
-  if (glib_poll) {
-    avahi_glib_poll_free (glib_poll);
-    glib_poll = NULL;
-  }
-
-  if (name) {
-    g_free (name);
-    name = NULL;
-  }
 }
 
-
-void PresencePublisher::publish (const Ekiga::PersonalDetails & details)
+void
+Avahi::PresencePublisher::client_callback (AvahiClient* client_,
+					   AvahiClientState state)
 {
-  std::string short_status;
-  int error = 0;
+  if (client_ == NULL)
+    return;
 
-  if (text_record) {
-    avahi_string_list_free (text_record);
-    text_record = NULL;
-  }
+  client = client_;
 
-  if (name) {
-    g_free (name); 
-    name = NULL;
-  }
+  switch (state) {
 
-  Ekiga::CallCore *call_core = dynamic_cast<Ekiga::CallCore *> (core.get ("call-core"));
-  if (call_core) {
+  case AVAHI_CLIENT_FAILURE:
 
-    to_publish.clear ();
-    Ekiga::CallCore::const_iterator it;
-    for (it = call_core->begin (); it != call_core->end (); it++)
-     to_publish = (*it)->get_interfaces ();
-  }
+    if (avahi_client_errno (client) == AVAHI_ERR_DISCONNECTED) {
 
-  name = g_strdup (details.get_display_name ().c_str ());
-  short_status = "presence-" + details.get_short_status ();
-  text_record = avahi_string_list_add_printf (text_record, "presence=%s", short_status.c_str ());
-  text_record = avahi_string_list_add_printf (text_record, "status=%s", details.get_long_status ().c_str ());
-  text_record = avahi_string_list_add (text_record, "software=Ekiga/" PACKAGE_VERSION);
-
-  if (client && group) {
-
-    avahi_entry_group_reset (group);
-    if (avahi_client_get_state(client) == AVAHI_CLIENT_S_RUNNING)
-      connect ();
-  }
-  else {
+      free_client ();
+      create_client ();
+    }
+    break;
+  case AVAHI_CLIENT_S_RUNNING:
 
-    /* Allocate a new client */
-    if (name) {
+    register_services ();
+    break;
 
-      client = avahi_client_new (poll_api, (AvahiClientFlags) 0, avahi_client_callback, this, &error);
-      if (client)
-        group = avahi_entry_group_new (client, avahi_entry_group_callback, this);
-    }
+  case AVAHI_CLIENT_S_REGISTERING:
+  case AVAHI_CLIENT_S_COLLISION:
+  case AVAHI_CLIENT_CONNECTING:
+  default:
+    break; // nothing
   }
 }
 
-
-bool PresencePublisher::connect () 
+void
+Avahi::PresencePublisher::register_services ()
 {
-  bool success = true;
-  int ret = 0;
+  remove_services ();
 
+  avahi_entry_group_new (client,
+			 (AvahiEntryGroupCallback)entry_group_cb, this);
+}
+
+void
+Avahi::PresencePublisher::remove_services ()
+{
   if (group != NULL) {
 
-    Ekiga::CallManager::InterfaceList::const_iterator it;
-    for (it = to_publish.begin (); it != to_publish.end (); it++) {
+    avahi_entry_group_free (group);
+    group = NULL;
+  }
+}
 
-      std::stringstream srv;
-      srv << "_" << (*it).voip_protocol << "._" << (*it).protocol;
+void
+Avahi::PresencePublisher::entry_group_callback (AvahiEntryGroup* group_,
+						AvahiEntryGroupState state)
+{
+  if (group_ == NULL)
+    return;
 
-      ret = avahi_entry_group_add_service_strlst (group,
-                                                  AVAHI_IF_UNSPEC,
-                                                  AVAHI_PROTO_UNSPEC,
-                                                  (AvahiPublishFlags) 0,
-                                                  name,
-                                                  srv.str ().c_str (),
-                                                  NULL,
-                                                  NULL,
-                                                  (*it).port,
-                                                  text_record);
-      if (ret >= 0) {
-
-        /* Commit changes */
-        ret = avahi_entry_group_commit (group);
-        if (ret < 0) 
-          success = false;
-      }
-      else {
-        success = false;
-      }
-    }
-  }
+  group = group_;
 
-  return success;
-}
+  switch (state) {
 
+  case AVAHI_ENTRY_GROUP_COLLISION: {
 
-void PresencePublisher::disconnect ()
-{
-  if (client) {
-    avahi_client_free (client);
-    client = NULL;
+    gchar *new_name = NULL;
+
+    new_name = avahi_alternative_service_name (name);
+    g_free (name);
+    name = new_name;
+    add_services ();
   }
+    break;
 
-  group = NULL;
-}
+  case AVAHI_ENTRY_GROUP_UNCOMMITED:
 
+    add_services ();
+    break;
 
-void PresencePublisher::client_callback (AvahiClient *_client, 
-                                         AvahiClientState state)
+  case AVAHI_ENTRY_GROUP_REGISTERING:
+  case AVAHI_ENTRY_GROUP_ESTABLISHED:
+  case AVAHI_ENTRY_GROUP_FAILURE:
+  default:
+    break; // nothing
+  }
+}
+
+void
+Avahi::PresencePublisher::add_services ()
 {
-  /* Called whenever the client or server state changes */
-  if (state == AVAHI_CLIENT_S_RUNNING) {
-   
-    /* The server has startup successfully and registered its host
-     * name on the network, so it's time to create our services */
-    connect ();
+  Ekiga::CallManager::InterfaceList interfaces;
+  AvahiStringList* txt_record = NULL;
+  int ret;
+
+  for (Ekiga::CallCore::const_iterator iter = call_core.begin ();
+       iter != call_core.end ();
+       ++iter) {
+
+    Ekiga::CallManager::InterfaceList ints = (*iter)->get_interfaces ();
+    interfaces.insert (interfaces.begin (), ints.begin (), ints.end ());
+
   }
-  else {
-    
-    if (state == AVAHI_CLIENT_S_COLLISION) {
-   
-      /* Let's drop our registered services. When the server is back
-       * in AVAHI_SERVER_RUNNING state we will register them
-       * again with the new host name. */
-      if (group)
-	avahi_entry_group_reset (group);
 
-    } else if (state == AVAHI_CLIENT_FAILURE) {
+  txt_record = prepare_txt_record ();
 
-      if (avahi_client_errno (_client) == AVAHI_ERR_DISCONNECTED) {
+  for (Ekiga::CallManager::InterfaceList::const_iterator iter = interfaces.begin ();
+       iter != interfaces.end ();
+       ++iter) {
 
-	g_timeout_add (60000, on_disconnect, this);
-      }
-    }
+    gchar *typ = NULL;
+
+    typ = g_strdup_printf ("_%s._%s",
+			   iter->voip_protocol.c_str (),
+			   iter->protocol.c_str ());
+
+    /* FIXME: no collision checking here */
+    ret = avahi_entry_group_add_service_strlst (group, AVAHI_IF_UNSPEC,
+						AVAHI_PROTO_UNSPEC,
+						(AvahiPublishFlags)0,
+						name, typ,
+						NULL, NULL,
+						iter->port, txt_record);
   }
+  avahi_string_list_free (txt_record);
+  ret = avahi_entry_group_commit (group);
 }
 
-
-void PresencePublisher::entry_group_callback (AvahiEntryGroup *_group,
-                                              AvahiEntryGroupState state)
+AvahiStringList*
+Avahi::PresencePublisher::prepare_txt_record ()
 {
-  char *n = NULL;
-  
-  /* Called whenever the entry group state changes */
-  if (state == AVAHI_ENTRY_GROUP_COLLISION) {
-
-    /* A service name collision happened. Let's pick a new name */
-    n = avahi_alternative_service_name (name);
-    avahi_free (name);
-    name = n;
-  }
+  AvahiStringList* result = NULL;
 
-  /* And recreate the services */
-  group = _group;
-  client = avahi_entry_group_get_client (group);
+  result = avahi_string_list_add_printf (result,
+					 "presence=%s",
+					 details.get_short_status ().c_str ());
+
+  result = avahi_string_list_add_printf (result,
+					 "status=%s",
+					 details.get_long_status ().c_str ());
+  result = avahi_string_list_add_printf (result,
+					 "display_name=%s",
+					 details.get_display_name ().c_str ());
 
-  connect ();
+  return result;
 }
-

Modified: trunk/lib/engine/components/avahi-publisher/avahi-publisher.h
==============================================================================
--- trunk/lib/engine/components/avahi-publisher/avahi-publisher.h	(original)
+++ trunk/lib/engine/components/avahi-publisher/avahi-publisher.h	Sun Aug 31 08:16:05 2008
@@ -1,6 +1,6 @@
 
 /* Ekiga -- A VoIP and Video-Conferencing application
- * Copyright (C) 2000-2006 Damien Sandras
+ * Copyright (C) 2000-2008 Damien Sandras
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -27,81 +27,77 @@
 
 
 /*
- *                         avahi_publish.h  -  description
+ *                         avahi-publisher.h  -  description
  *                         ------------------------------------
  *   begin                : Sun Aug 21 2005
- *   copyright            : (C) 2005 by Sebastien Estienne 
- *   description          : This file contains the Avahi zeroconf publisher. 
+ *   copyright            : (C) 2005 by Sebastien Estienne
+ *                          (C) 2008 by Julien Puydt
+ *   description          : Avahi publisher declaration
  *
  */
 
+#ifndef __AVAHI_PUBLISHER_H__
+#define __AVAHI_PUBLISHER_H__
 
-#ifndef _AVAHI_PUBLISHER_H_
-#define _AVAHI_PUBLISHER_H_
+#include "services.h"
+#include "personal-details.h"
+#include "presence-core.h"
+#include "call-manager.h"
 
-#include <avahi-client/client.h>
-#include <avahi-client/publish.h>
 #include <avahi-common/alternative.h>
-#include <avahi-common/malloc.h>
 #include <avahi-common/error.h>
-#include <avahi-common/timeval.h>
+#include <avahi-common/malloc.h>
+#include <avahi-common/strlst.h>
+#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
 #include <avahi-glib/glib-watch.h>
 
-#include "presence-core.h"
-#include "services.h"
-
-#include "call-manager.h"
-
-namespace Ekiga {
-  class PersonalDetails;
-}
-
 namespace Avahi
 {
-  class PresencePublisher 
-    : public Ekiga::PresencePublisher,
-      public Ekiga::Service
+  class PresencePublisher: public Ekiga::Service,
+			   public Ekiga::PresencePublisher
   {
 public:
-    PresencePublisher (Ekiga::ServiceCore & core);
+
+    PresencePublisher (Ekiga::ServiceCore& core,
+		       Ekiga::PersonalDetails& details,
+		       Ekiga::CallCore& call_core);
+
     ~PresencePublisher ();
 
-    
-    /*** Service API ***/
     const std::string get_name () const
       { return "avahi-presence-publisher"; }
 
     const std::string get_description () const
       { return "\tObject bringing in Avahi presence publishing"; }
 
-    
-    /*** PresencePublisher API ***/
     void publish (const Ekiga::PersonalDetails & details);
 
+    /* public only to be called by C callbacks... */
+    void client_callback (AvahiClient* client,
+			  AvahiClientState state);
+    void entry_group_callback (AvahiEntryGroup* group,
+			       AvahiEntryGroupState state);
 
-    /*** Avahi::PresencePublisher API ***/
-    bool connect (); 
-    void disconnect ();
+private:
 
-    void client_callback (AvahiClient *client, 
-                          AvahiClientState state);
+    Ekiga::ServiceCore& core;
+    Ekiga::PersonalDetails& details;
+    Ekiga::CallCore& call_core;
 
-    void entry_group_callback (AvahiEntryGroup *group, 
-                               AvahiEntryGroupState state);
+    AvahiGLibPoll* glib_poll;
 
-private:
-    Ekiga::ServiceCore & core;
+    void create_client ();
+    void free_client ();
     AvahiClient *client;
-    AvahiEntryGroup *group;
-
-    char *name;                    /* Srv Record */
-    uint16_t port;                 /* port number of Srv Record */
-    AvahiStringList *text_record;  /* H323 Txt Record */
 
-    AvahiGLibPoll *glib_poll;
-    const AvahiPoll *poll_api;
+    void register_services ();
+    void add_services ();
+    void remove_services ();
+    AvahiEntryGroup* group;
+    gchar* name;
 
-    Ekiga::CallManager::InterfaceList to_publish;
+    AvahiStringList* prepare_txt_record ();;
   };
 };
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]