[ekiga] Opal: Several changes.



commit f8783f4695b7b070183c11c082209e18d00d331e
Author: Damien Sandras <dsandras seconix com>
Date:   Sun Jan 11 13:54:43 2015 +0100

    Opal: Several changes.
    
    Well, I should really do smaller commits.
    
    - Added new methods to enable/disable accounts that do not work on a
      const Account reference. Enabling an Account will change some of its
      internal details (like its registration status). Working with const
      references did not make sense here.
    
    - Added TCP transport support to Opal SIP Accounts. We now work as
      recommended by RFCs with a kind of TCPPrefered default. We only
      fallback to UDP if things do not work with TCP.
    
    - Removed unneeded thread to register/unregister in the SIP EndPoint.
      OPAL now handles things asynchronously.

 lib/engine/components/opal/opal-account.cpp |  190 +++++++++-----------
 lib/engine/components/opal/opal-account.h   |   16 +-
 lib/engine/components/opal/opal-bank.cpp    |   11 +-
 lib/engine/components/opal/opal-bank.h      |    1 +
 lib/engine/components/opal/sip-endpoint.cpp |  263 +++++++++------------------
 lib/engine/components/opal/sip-endpoint.h   |   28 ++--
 6 files changed, 201 insertions(+), 308 deletions(-)
---
diff --git a/lib/engine/components/opal/opal-account.cpp b/lib/engine/components/opal/opal-account.cpp
index 1415d4c..3fdfb16 100644
--- a/lib/engine/components/opal/opal-account.cpp
+++ b/lib/engine/components/opal/opal-account.cpp
@@ -57,6 +57,7 @@
 
 #include "opal-presentity.h"
 #include "sip-endpoint.h"
+#include "h323-endpoint.h"
 
 // remove leading and trailing spaces and tabs (useful for copy/paste)
 // also, if no protocol specified, add leading "sip:"
@@ -143,6 +144,7 @@ Opal::Account::build_node(Opal::Account::Type typus,
 
 Opal::Account::Account (Opal::Bank & _bank,
                         boost::shared_ptr<Opal::Sip::EndPoint> _sip_endpoint,
+                        boost::shared_ptr<Opal::H323::EndPoint> _h323_endpoint,
                        boost::weak_ptr<Ekiga::PresenceCore> _presence_core,
                        boost::shared_ptr<Ekiga::NotificationCore> _notification_core,
                        boost::shared_ptr<Ekiga::PersonalDetails> _personal_details,
@@ -154,6 +156,7 @@ Opal::Account::Account (Opal::Bank & _bank,
   node(_node),
   bank(_bank),
   sip_endpoint(_sip_endpoint),
+  h323_endpoint(_h323_endpoint),
   presence_core(_presence_core),
   notification_core(_notification_core),
   personal_details(_personal_details),
@@ -168,15 +171,6 @@ Opal::Account::Account (Opal::Bank & _bank,
 
   decide_type ();
 
-  if (type != Account::H323) {
-
-    const std::string name = get_name ();
-    if (name.find ("%limit") != std::string::npos)
-      compat_mode = SIPRegister::e_CannotRegisterMultipleContacts;  // start registration in this compat mode
-    else
-      compat_mode = SIPRegister::e_FullyCompliant;
-  }
-
   for (xmlNodePtr child = node->children; child != NULL; child = child->next) {
 
     if (child->type == XML_ELEMENT_NODE && child->name != NULL && xmlStrEqual (BAD_CAST "roster", 
child->name)) {
@@ -199,8 +193,6 @@ Opal::Account::Account (Opal::Bank & _bank,
     }
   }
 
-  setup_presentity ();
-
   /* Actor stuff */
   add_action (Ekiga::ActionPtr (new Ekiga::Action ("add-contact", _("A_dd Contact"),
                                                    boost::bind (&Opal::Account::add_contact, this))));
@@ -492,12 +484,25 @@ Opal::Account::set_authentication_settings (const std::string& username,
 void
 Opal::Account::enable ()
 {
+  PString _aor;
   xmlSetProp (node, BAD_CAST "enabled", BAD_CAST "true");
 
   state = Processing;
   status = _("Processing...");
-  call_manager->subscribe (*this, presentity);
 
+  /* Actual registration code */
+  switch (type) {
+  case Account::H323:
+    h323_endpoint->enable_account (*this);
+    break;
+  case Account::SIP:
+  case Account::DiamondCard:
+  case Account::Ekiga:
+  default:
+    // Register the given aor to the given registrar
+    sip_endpoint->enable_account (*this);
+    break;
+  }
   updated ();
   trigger_saving ();
 
@@ -522,13 +527,20 @@ Opal::Account::disable ()
     }
   }
 
-  if (type == Account::H323)
-    call_manager->unsubscribe (*this, presentity);
-  else {
-
-      call_manager->unsubscribe (*this, presentity);
-      sip_endpoint->Unsubscribe (SIPSubscribe::MessageSummary, get_aor ());
-    }
+  /* Actual unregistration code */
+  switch (type) {
+  case Account::H323:
+    h323_endpoint->disable_account (*this);
+    break;
+  case Account::SIP:
+  case Account::DiamondCard:
+  case Account::Ekiga:
+  default:
+    // Register the given aor to the given registrar
+    sip_endpoint->disable_account (*this);
+    sip_endpoint->Unsubscribe (SIPSubscribe::MessageSummary, get_aor ());
+    break;
+  }
 
   // Translators: this is a state, not an action, i.e. it should be read as
   // "(you are) unregistered", and not as "(you have been) unregistered"
@@ -575,13 +587,6 @@ Opal::Account::is_active () const
 }
 
 
-SIPRegister::CompatibilityModes
-Opal::Account::get_compat_mode () const
-{
-  return compat_mode;
-}
-
-
 void
 Opal::Account::remove ()
 {
@@ -880,7 +885,7 @@ Opal::Account::fetch (const std::string uri) const
   // Subscribe now
   if (state == Registered) {
     PTRACE(4, "Ekiga\tSubscribeToPresence for " << uri.c_str () << " (fetch)");
-    presentity->SubscribeToPresence (PString (uri));
+    presentity->SubscribeToPresence (get_transaction_aor (uri).c_str ());
   }
 }
 
@@ -889,7 +894,7 @@ void
 Opal::Account::unfetch (const std::string uri) const
 {
   if (is_myself (uri) && presentity) {
-    presentity->UnsubscribeFromPresence (PString (uri));
+    presentity->UnsubscribeFromPresence (get_transaction_aor (uri).c_str ());
     Ekiga::Runtime::run_in_main (boost::bind (&Opal::Account::presence_status_in_main, this, uri, "unknown", 
""));
   }
 }
@@ -897,7 +902,7 @@ Opal::Account::unfetch (const std::string uri) const
 
 void
 Opal::Account::handle_registration_event (Ekiga::Account::RegistrationState state_,
-                                         const std::string info) const
+                                         const std::string info)
 {
   switch (state_) {
 
@@ -910,9 +915,22 @@ Opal::Account::handle_registration_event (Ekiga::Account::RegistrationState stat
       status = _("Registered");
       state = state_;
       failed_registration_already_notified = false;
+
+      PURL url = PString (get_transaction_aor (get_aor ()));
+      presentity = call_manager->AddPresentity (url);
       if (presentity) {
 
-        for (Ekiga::RefLister<Presentity>::const_iterator iter = Ekiga::RefLister<Presentity>::begin ();
+        presentity->SetPresenceChangeNotifier (PCREATE_PresenceChangeNotifier (OnPresenceChange));
+        presentity->GetAttributes().Set(OpalPresentity::AuthNameKey, get_authentication_username ());
+        presentity->GetAttributes().Set(OpalPresentity::AuthPasswordKey, get_password ());
+        if (type != H323) {
+          presentity->GetAttributes().Set(SIP_Presentity::SubProtocolKey, "Agent");
+        }
+        PTRACE (4, "Created presentity for " << get_aor());
+
+        presentity->Open ();
+
+        for (Ekiga::RefLister<Presentity>::iterator iter = Ekiga::RefLister<Presentity>::begin ();
              iter != Ekiga::RefLister<Presentity>::end ();
              ++iter)
           fetch ((*iter)->get_uri());
@@ -926,7 +944,7 @@ Opal::Account::handle_registration_event (Ekiga::Account::RegistrationState stat
       if (details)
         const_cast<Account*>(this)->publish (*details);
 
-      updated ();
+      Ekiga::Runtime::run_in_main (boost::ref (updated));
     }
     break;
 
@@ -938,11 +956,14 @@ Opal::Account::handle_registration_event (Ekiga::Account::RegistrationState stat
     failed_registration_already_notified = false;
     state = state_;
 
-    updated ();
+    if (presentity)
+      presentity->Close ();
+
+    Ekiga::Runtime::run_in_main (boost::ref (updated));
     /* delay destruction of this account until the
        unsubscriber thread has called back */
     if (dead)
-      removed ();
+      Ekiga::Runtime::run_in_main (boost::ref (removed));
     break;
 
   case UnregistrationFailed:
@@ -952,7 +973,7 @@ Opal::Account::handle_registration_event (Ekiga::Account::RegistrationState stat
     failed_registration_already_notified = false;
     if (!info.empty ())
       status = status + " (" + info + ")";
-    updated ();
+    Ekiga::Runtime::run_in_main (boost::ref (updated));
     break;
 
   case RegistrationFailed:
@@ -967,58 +988,22 @@ Opal::Account::handle_registration_event (Ekiga::Account::RegistrationState stat
          ncore->push_notification (notif);
     }
     else {
-      switch (compat_mode) {
-      case SIPRegister::e_FullyCompliant:
-        // FullyCompliant did not work, try next compat mode
-        compat_mode = SIPRegister::e_CannotRegisterMultipleContacts;
-        PTRACE (4, "Register failed in FullyCompliant mode, retrying in CannotRegisterMultipleContacts 
mode");
-        call_manager->subscribe (*this, presentity);
-        break;
-      case SIPRegister::e_CannotRegisterMultipleContacts:
-        // CannotRegMC did not work, try next compat mode
-        compat_mode = SIPRegister::e_CannotRegisterPrivateContacts;
-        PTRACE (4, "Register failed in CannotRegisterMultipleContacts mode, retrying in 
CannotRegisterPrivateContacts mode");
-        call_manager->subscribe (*this, presentity);
-        break;
-      case SIPRegister::e_CannotRegisterPrivateContacts:
-        // CannotRegPC did not work, try next compat mode
-        compat_mode = SIPRegister::e_HasApplicationLayerGateway;
-        PTRACE (4, "Register failed in CannotRegisterPrivateContacts mode, retrying in 
HasApplicationLayerGateway mode");
-        call_manager->subscribe (*this, presentity);
-        break;
-      case SIPRegister::e_HasApplicationLayerGateway:
-        // HasAppLG did not work, try next compat mode
-        compat_mode = SIPRegister::e_RFC5626;
-        PTRACE (4, "Register failed in HasApplicationLayerGateway mode, retrying in RFC5626 mode");
-        call_manager->subscribe (*this, presentity);
-        break;
-      case SIPRegister::e_RFC5626:
-        // RFC5626 did not work, stop registration with error
-        compat_mode = SIPRegister::e_FullyCompliant;
-        PTRACE (4, "Register failed in RFC5626 mode, aborting registration");
-        status = _("Could not register");
-        if (!info.empty ())
-          status = status + " (" + info + ")";
-        if (!failed_registration_already_notified) {
-          std::stringstream msg;
-          msg << _("Could not register to ") << get_name ();
-          boost::shared_ptr<Ekiga::Notification> notif (new Ekiga::Notification 
(Ekiga::Notification::Warning, msg.str (), info, _("Edit"), boost::bind (&Opal::Account::edit, 
(Opal::Account*) this)));
-          boost::shared_ptr<Ekiga::NotificationCore> ncore = notification_core.lock ();
-          if (ncore)
-            ncore->push_notification (notif);
-          updated ();
-        }
-        failed_registration_already_notified = true;
-        break;
-      case SIPRegister::EndCompatibilityModes:
-        // bookkeeping code, to remove a compile warning
-        break;
-      default:
-
-        state = state_;
-        updated();
-        break;
+
+      // RFC5626 did not work, stop registration with error
+      PTRACE (4, "Register failed in RFC5626 mode, aborting registration");
+      status = _("Could not register");
+      if (!info.empty ())
+        status = status + " (" + info + ")";
+      if (!failed_registration_already_notified) {
+        std::stringstream msg;
+        msg << _("Could not register to ") << get_name ();
+        boost::shared_ptr<Ekiga::Notification> notif (new Ekiga::Notification (Ekiga::Notification::Warning, 
msg.str (), info, _("Edit"), boost::bind (&Opal::Account::edit, (Opal::Account*) this)));
+        boost::shared_ptr<Ekiga::NotificationCore> ncore = notification_core.lock ();
+        if (ncore)
+          ncore->push_notification (notif);
+        Ekiga::Runtime::run_in_main (boost::ref (updated));
       }
+      failed_registration_already_notified = true;
     }
     break;
 
@@ -1026,11 +1011,11 @@ Opal::Account::handle_registration_event (Ekiga::Account::RegistrationState stat
 
     state = state_;
     status = _("Processing...");
-    updated ();
+    Ekiga::Runtime::run_in_main (boost::ref (updated));
   default:
 
     state = state_;
-    updated();
+    Ekiga::Runtime::run_in_main (boost::ref (updated));
     break;
   }
 }
@@ -1062,25 +1047,6 @@ Opal::Account::get_type () const
   return type;
 }
 
-void
-Opal::Account::setup_presentity ()
-{
-  PURL url = PString (get_aor ());
-  presentity = call_manager->AddPresentity (url);
-
-  if (presentity) {
-
-    presentity->SetPresenceChangeNotifier (PCREATE_PresenceChangeNotifier (OnPresenceChange));
-    presentity->GetAttributes().Set(OpalPresentity::AuthNameKey, get_authentication_username ());
-    presentity->GetAttributes().Set(OpalPresentity::AuthPasswordKey, get_password ());
-    if (type != H323) {
-      presentity->GetAttributes().Set(SIP_Presentity::SubProtocolKey, "Agent");
-    }
-    PTRACE (4, "Created presentity for " << get_aor());
-  } else
-    PTRACE (4, "Error: cannot create presentity for " << get_aor());
-}
-
 
 void
 Opal::Account::OnPresenceChange (OpalPresentity& /*presentity*/,
@@ -1354,6 +1320,8 @@ Opal::Account::on_rename_group_form_submitted (bool submitted,
   return true;
 }
 
+
+// FIXME: This is awful
 void
 Opal::Account::decide_type ()
 {
@@ -1368,3 +1336,13 @@ Opal::Account::decide_type ()
   else
     type = Account::H323;
 }
+
+
+const std::string
+Opal::Account::get_transaction_aor (const std::string & aor) const
+{
+  if (sip_endpoint->IsRegistered (get_aor () + ";transport=tcp"))
+    return aor + ";transport=tcp";
+  else
+    return aor;
+}
diff --git a/lib/engine/components/opal/opal-account.h b/lib/engine/components/opal/opal-account.h
index 7309012..d71fec7 100644
--- a/lib/engine/components/opal/opal-account.h
+++ b/lib/engine/components/opal/opal-account.h
@@ -59,6 +59,7 @@ namespace Opal
   class CallManager;
   class Presentity;
   namespace Sip { class EndPoint; };
+  namespace H323 { class EndPoint; };
 
   /**
    * @addtogroup accounts
@@ -87,6 +88,7 @@ public:
 
     Account (Opal::Bank & bank,
              boost::shared_ptr<Opal::Sip::EndPoint> _sip_endpoint,
+             boost::shared_ptr<Opal::H323::EndPoint> _h323_endpoint,
             boost::weak_ptr<Ekiga::PresenceCore> _presence_core,
             boost::shared_ptr<Ekiga::NotificationCore> _notification_core,
             boost::shared_ptr<Ekiga::PersonalDetails> _personal_details,
@@ -157,8 +159,6 @@ public:
 
     bool is_active () const;
 
-    SIPRegister::CompatibilityModes get_compat_mode () const;
-
     void remove ();
 
     void edit ();
@@ -176,7 +176,7 @@ public:
      * want its Register method to take a const account...
      */
     void handle_registration_event (RegistrationState state_,
-                                   const std::string info) const;
+                                   const std::string info);
 
     /* This method is public to be called by an opal endpoint, which will push
      * this Opal::Account's message waiting information
@@ -201,6 +201,8 @@ private:
 
     void decide_type ();
 
+    const std::string get_transaction_aor (const std::string & aor) const;
+
     void add_contact ();
     bool on_add_contact_form_submitted (bool submitted,
                                        Ekiga::Form& result,
@@ -221,16 +223,13 @@ private:
     mutable RegistrationState state;
     bool dead;
     bool failed;
-    mutable SIPRegister::CompatibilityModes compat_mode;
     std::string aid;
-    mutable std::string status;  // the state, as a string
+    std::string status;  // the state, as a string
     int message_waiting_number;
     std::string protocol_name;
 
-    mutable bool failed_registration_already_notified;
-
+    bool failed_registration_already_notified;
     PSafePtr<OpalPresentity> presentity;
-    void setup_presentity ();
 
     PDECLARE_PresenceChangeNotifier (Account, OnPresenceChange);
 
@@ -248,6 +247,7 @@ private:
     Opal::Bank & bank;
 
     boost::shared_ptr<Opal::Sip::EndPoint> sip_endpoint;
+    boost::shared_ptr<Opal::H323::EndPoint> h323_endpoint;
     boost::weak_ptr<Ekiga::PresenceCore> presence_core;
     boost::weak_ptr<Ekiga::NotificationCore> notification_core;
     boost::weak_ptr<Ekiga::PersonalDetails> personal_details;
diff --git a/lib/engine/components/opal/opal-bank.cpp b/lib/engine/components/opal/opal-bank.cpp
index b6f7c8c..e2ea9fc 100644
--- a/lib/engine/components/opal/opal-bank.cpp
+++ b/lib/engine/components/opal/opal-bank.cpp
@@ -48,11 +48,13 @@
 #include "opal-bank.h"
 #include "opal-presentity.h"
 #include "sip-endpoint.h"
+#include "h323-endpoint.h"
 
 
 Opal::Bank::Bank (Ekiga::ServiceCore& core):
   is_call_manager_ready(false),
   sip_endpoint(core.get<Opal::Sip::EndPoint> ("opal-sip-endpoint")),
+  h323_endpoint(core.get<Opal::H323::EndPoint> ("opal-h323-endpoint")),
   presence_core(core.get<Ekiga::PresenceCore> ("presence-core")),
   notification_core(core.get<Ekiga::NotificationCore> ("notification-core")),
   personal_details(core.get<Ekiga::PersonalDetails> ("personal-details")),
@@ -87,6 +89,7 @@ Opal::Bank::Bank (Ekiga::ServiceCore& core):
 
       boost::shared_ptr<Account> account(new Account (*this,
                                                       sip_endpoint,
+                                                      h323_endpoint,
                                                       presence_core,
                                                       notification_core,
                                                       personal_details,
@@ -262,6 +265,7 @@ Opal::Bank::add (Account::Type acc_type,
   AccountPtr account
     = AccountPtr(new Opal::Account (*this,
                                     sip_endpoint,
+                                    h323_endpoint,
                                    presence_core,
                                    notification_core,
                                    personal_details,
@@ -299,9 +303,14 @@ Opal::Bank::call_manager_ready ()
 
 
 Opal::AccountPtr
-Opal::Bank::find_account (const std::string& aor)
+Opal::Bank::find_account (const std::string& _aor)
 {
   AccountPtr result;
+  std::string aor = _aor;
+  std::string::size_type t = aor.find_first_of (";");
+
+  if (t != std::string::npos)
+    aor = aor.substr (0, t);
 
   for (iterator iter = begin ();
        iter != end ();
diff --git a/lib/engine/components/opal/opal-bank.h b/lib/engine/components/opal/opal-bank.h
index be38931..303f803 100644
--- a/lib/engine/components/opal/opal-bank.h
+++ b/lib/engine/components/opal/opal-bank.h
@@ -116,6 +116,7 @@ private:
     bool is_call_manager_ready;
 
     boost::shared_ptr<Opal::Sip::EndPoint> sip_endpoint;
+    boost::shared_ptr<Opal::H323::EndPoint> h323_endpoint;
     boost::weak_ptr<Ekiga::PresenceCore> presence_core;
     boost::shared_ptr<Ekiga::NotificationCore> notification_core;
     boost::shared_ptr<Ekiga::PersonalDetails> personal_details;
diff --git a/lib/engine/components/opal/sip-endpoint.cpp b/lib/engine/components/opal/sip-endpoint.cpp
index 35add90..97017e3 100644
--- a/lib/engine/components/opal/sip-endpoint.cpp
+++ b/lib/engine/components/opal/sip-endpoint.cpp
@@ -41,81 +41,12 @@
 #include "sip-endpoint.h"
 #include "chat-core.h"
 
-namespace Opal {
-
-  namespace Sip {
-
-    class subscriber : public PThread
-    {
-      PCLASSINFO(subscriber, PThread);
-
-    public:
-      subscriber (std::string _username,
-                 std::string _host,
-                 std::string _authentication_username,
-                 std::string _password,
-                 bool _is_enabled,
-                 SIPRegister::CompatibilityModes _compat_mode,
-                 unsigned _timeout,
-                 std::string _aor,
-                  Opal::Sip::EndPoint & _manager,
-                 bool _registering,
-                  const PSafePtr<OpalPresentity> & _presentity)
-        : PThread (1000, AutoDeleteThread),
-         username(_username),
-         host(_host),
-         authentication_username(_authentication_username),
-         password(_password),
-         is_enabled(_is_enabled),
-         compat_mode(_compat_mode),
-         timeout(_timeout),
-         aor(_aor),
-         manager (_manager),
-         registering (_registering),
-         presentity (_presentity)
-      {
-        this->Resume ();
-      };
-
-      void Main ()
-      {
-       if (registering) {
-
-          if (presentity && !presentity->IsOpen ())
-            presentity->Open ();
-         manager.Register (username, host, authentication_username, password, is_enabled, compat_mode, 
timeout);
-       }
-        else {
-         manager.Unregister (aor);
-
-          if (presentity && presentity->IsOpen ())
-            presentity->Close ();
-       }
-      };
-
-    private:
-      std::string username;
-      std::string host;
-      std::string authentication_username;
-      std::string password;
-      bool is_enabled;
-      SIPRegister::CompatibilityModes compat_mode;
-      unsigned timeout;
-      std::string aor;
-      Opal::Sip::EndPoint & manager;
-      bool registering;
-      const PSafePtr<OpalPresentity> & presentity;
-    };
-  };
-};
-
-
 
 /* The class */
 Opal::Sip::EndPoint::EndPoint (Opal::CallManager & _manager,
-                               Ekiga::ServiceCore& core):
-  SIPEndPoint (_manager),
-  manager (_manager)
+                               const Ekiga::ServiceCore& _core): SIPEndPoint (_manager),
+                                                                 manager (_manager),
+                                                                 core (_core)
 {
   boost::shared_ptr<Ekiga::ChatCore> chat_core = core.get<Ekiga::ChatCore> ("chat-core");
   boost::shared_ptr<Ekiga::PresenceCore> presence_core = core.get<Ekiga::PresenceCore> ("presence-core");
@@ -308,39 +239,47 @@ bool
 Opal::Sip::EndPoint::set_listen_port (unsigned port)
 {
   unsigned udp_min, udp_max;
-
-  listen_iface.protocol = "udp";
-  listen_iface.voip_protocol = "sip";
-  listen_iface.id = "*";
+  unsigned tcp_min, tcp_max;
 
   manager.get_udp_ports (udp_min, udp_max);
+  manager.get_tcp_ports (tcp_min, tcp_max);
+
+  const std::string protocols[] = { "udp", "tcp", "" };
+  const unsigned ports[][2] = { { udp_min, udp_max }, { tcp_min, tcp_max } };
 
   if (port > 0) {
 
-    std::stringstream str;
+    interfaces.clear ();
     RemoveListener (NULL);
+    for (int i = 0 ; !protocols[i].empty () ; i++) {
 
-    str << "udp$*:" << port;
-    if (!StartListeners (PStringArray (str.str ()))) {
+      std::stringstream str;
+      str << protocols[i] << "$*:" << port;
+      listen_iface.protocol = protocols[i];
+      listen_iface.voip_protocol = "sip";
+      listen_iface.id = "*";
+      if (!StartListeners (PStringArray (str.str ()))) {
 
-      port = udp_min;
-      while (port <= udp_max) {
-        str << "udp$*:" << port;
+        port = ports[i][0];
+        while (port <= ports[i][1]) {
+          str << protocols[i] << "$*:" << port;
 
-        if (StartListeners (PStringArray (str.str ()))) {
+          if (StartListeners (PStringArray (str.str ()))) {
 
-          listen_iface.port = port;
-         PTRACE (4, "Opal::Sip::EndPoint\tSet listen port to " << port);
-          return true;
-        }
+            PTRACE (4, "Opal::Sip::EndPoint\tSet listen port to " << port << " (" << protocols[i] << ")");
+            listen_iface.port = port;
+            interfaces.push_back (listen_iface);
+            break;
+          }
 
-        port++;
+          port++;
+        }
+      }
+      else {
+        listen_iface.port = port;
+        interfaces.push_back (listen_iface);
+        PTRACE (4, "Opal::Sip::EndPoint\tSet listen port to " << port << " (" << protocols[i] << ")");
       }
-    }
-    else {
-      listen_iface.port = port;
-      PTRACE (4, "Opal::Sip::EndPoint\tSet listen port to " << port);
-      return true;
     }
   }
 
@@ -348,14 +287,13 @@ Opal::Sip::EndPoint::set_listen_port (unsigned port)
 }
 
 
-const Ekiga::CallProtocolManager::Interface&
-Opal::Sip::EndPoint::get_listen_interface () const
+const Ekiga::CallProtocolManager::InterfaceList &
+Opal::Sip::EndPoint::get_interfaces () const
 {
-  return listen_iface;
+  return interfaces;
 }
 
 
-
 void
 Opal::Sip::EndPoint::set_forward_uri (const std::string & uri)
 {
@@ -427,112 +365,81 @@ Opal::Sip::EndPoint::get_aor_domain (const std::string & aor)
 }
 
 
-bool
-Opal::Sip::EndPoint::subscribe (const Opal::Account & account,
-                                const PSafePtr<OpalPresentity> & presentity)
-{
-  if (account.get_protocol_name () != "SIP")
-    return false;
-
-  new subscriber (account.get_username (),
-                 account.get_host (),
-                 account.get_authentication_username (),
-                 account.get_password (),
-                 account.is_enabled (),
-                 account.get_compat_mode (),
-                 account.get_timeout (),
-                 account.get_aor (),
-                 *this,
-                  true,
-                  presentity);
-  return true;
-}
-
-
-bool
-Opal::Sip::EndPoint::unsubscribe (const Opal::Account & account,
-                                  const PSafePtr<OpalPresentity> & presentity)
-{
-  if (account.get_protocol_name () != "SIP")
-    return false;
-
-  new subscriber (account.get_username (),
-                 account.get_host (),
-                 account.get_authentication_username (),
-                 account.get_password (),
-                 account.is_enabled (),
-                 account.get_compat_mode (),
-                 account.get_timeout (),
-                 account.get_aor (),
-                 *this,
-                  false,
-                  presentity);
-  return true;
-}
-
-
 void
-Opal::Sip::EndPoint::Register (const std::string username,
-                              const std::string host_,
-                              const std::string auth_username,
-                              const std::string password,
-                              bool is_enabled,
-                              SIPRegister::CompatibilityModes compat_mode,
-                              unsigned timeout)
+Opal::Sip::EndPoint::enable_account (Account & account)
 {
   PString _aor;
-  std::string host(host_);
-  std::string::size_type loc = host.find (":", 0);
-  if (loc != std::string::npos)
-    host = host.substr (0, loc);
 
   SIPRegister::Params params;
-  params.m_addressOfRecord = PString (username);
-  params.m_registrarAddress = PString (host_);
-  params.m_compatibility = compat_mode;
-  params.m_authID = auth_username;
-  params.m_password = password;
-  params.m_expire = is_enabled ? timeout : 0;
+  params.m_addressOfRecord = "sip:" + account.get_username () + "@" + account.get_host () + ";transport=tcp";
+  params.m_compatibility = SIPRegister::e_RFC5626;
+  params.m_authID = account.get_authentication_username ();
+  params.m_password = account.get_password ();
+  params.m_expire = account.is_enabled () ? account.get_timeout () : 0;
   params.m_minRetryTime = PMaxTimeInterval;  // use default value
   params.m_maxRetryTime = PMaxTimeInterval;  // use default value
 
   // Register the given aor to the given registrar
   if (!SIPEndPoint::Register (params, _aor)) {
-    SIPEndPoint::RegistrationStatus status;
-    status.m_wasRegistering = true;
-    status.m_reRegistering = false;
-    status.m_userData = NULL;
-    status.m_reason = SIP_PDU::Local_TransportError;
-    status.m_addressofRecord = PString (username);
-
-    OnRegistrationStatus (status);
+    params.m_addressOfRecord = "sip:" + account.get_username () + "@" + account.get_host ();
+    if (!SIPEndPoint::Register (params, _aor))
+      account.handle_registration_event (Account::RegistrationFailed,
+                                         _("Transport error"));
   }
 }
 
+
+void
+Opal::Sip::EndPoint::disable_account (Account & account)
+{
+  PString aor = "sip:" + account.get_username () + "@" + account.get_host ();
+  if (!IsRegistered (aor))
+    aor += ";transport=tcp";
+
+  if (!IsRegistered (aor))
+    return;
+
+  Unregister (aor);
+}
+
+
 void
 Opal::Sip::EndPoint::OnRegistrationStatus (const RegistrationStatus & status)
 {
-  std::string aor = (const char *) status.m_addressofRecord;
   std::string info;
-  std::stringstream strm;
 
-  if (status.m_reason == SIP_PDU::Information_Trying)
+  boost::shared_ptr<Opal::Bank> bank = core.get<Opal::Bank> ("opal-account-store");
+  Opal::AccountPtr account = bank->find_account (status.m_addressofRecord);
+  if (!account)
     return;
 
-  if (aor.find (uri_prefix) == std::string::npos)
-    strm << uri_prefix << aor;
-  else
-    strm << aor;
+  if (status.m_reason == SIP_PDU::Information_Trying)
+    return;
 
   SIPEndPoint::OnRegistrationStatus (status);
 
   /* Successful registration or unregistration */
   if (status.m_reason == SIP_PDU::Successful_OK) {
-
-    Ekiga::Runtime::run_in_main (boost::bind (boost::ref(registration_event), strm.str(), 
status.m_wasRegistering ? Account::Registered : Account::Unregistered, std::string ()));
+    account->handle_registration_event (status.m_wasRegistering?Account::Registered:Account::Unregistered,
+                                        std::string ());
   }
   /* Registration or unregistration failure */
   else {
+    SIPURL m_addressOfRecord = SIPURL (status.m_addressofRecord);
+    if (m_addressOfRecord.GetTransportProto () == "TCP") {
+      SIPRegister::Params params;
+      PString _aor;
+      m_addressOfRecord.SetParamVar ("transport", "udp");
+      params.m_addressOfRecord = m_addressOfRecord;
+      params.m_compatibility = SIPRegister::e_RFC5626;
+      params.m_authID = status.m_handler->GetAuthID ();
+      params.m_password = status.m_handler->GetPassword ();
+      params.m_expire = status.m_handler->GetExpire ();
+      params.m_minRetryTime = PMaxTimeInterval;  // use default value
+      params.m_maxRetryTime = PMaxTimeInterval;  // use default value
+      SIPEndPoint::Register (params, _aor);
+      return;
+    }
 
     /* all these codes are defined in opal, file include/sip/sippdu.h */
     switch (status.m_reason) {
@@ -769,9 +676,9 @@ Opal::Sip::EndPoint::OnRegistrationStatus (const RegistrationStatus & status)
     /* Opal adds a RequestTerminated, and this should not be shown to user,
      * as a sip code has already been scheduled to be shown
      */
-    if (status.m_reason != SIP_PDU::Failure_RequestTerminated) {
-      Ekiga::Runtime::run_in_main (boost::bind (boost::ref (registration_event), strm.str (), 
status.m_wasRegistering ? Account::RegistrationFailed : Account::UnregistrationFailed, info));
-    }
+    if (status.m_reason != SIP_PDU::Failure_RequestTerminated)
+      account->handle_registration_event 
(status.m_wasRegistering?Account::RegistrationFailed:Account::UnregistrationFailed,
+                                          info);
   }
 }
 
diff --git a/lib/engine/components/opal/sip-endpoint.h b/lib/engine/components/opal/sip-endpoint.h
index 4104755..d50b928 100644
--- a/lib/engine/components/opal/sip-endpoint.h
+++ b/lib/engine/components/opal/sip-endpoint.h
@@ -69,7 +69,7 @@ namespace Opal {
       typedef std::list<std::string>::iterator domain_list_iterator;
 
       EndPoint (CallManager& ep,
-               Ekiga::ServiceCore& core);
+               const Ekiga::ServiceCore& core);
 
       ~EndPoint ();
 
@@ -104,7 +104,8 @@ namespace Opal {
       unsigned get_dtmf_mode () const;
 
       bool set_listen_port (unsigned port);
-      const Ekiga::CallProtocolManager::Interface& get_listen_interface () const;
+
+      const Ekiga::CallProtocolManager::InterfaceList & get_interfaces () const;
 
 
       /* SIP EndPoint */
@@ -126,25 +127,19 @@ namespace Opal {
       // the parameters are the aor and the info
       boost::signals2::signal<void(std::string, std::string)> mwi_event;
 
-      /* AccountSubscriber */
-      bool subscribe (const Opal::Account & account, const PSafePtr<OpalPresentity> & presentity);
-      bool unsubscribe (const Opal::Account & account, const PSafePtr<OpalPresentity> & presentity);
-
-
       /* Helpers */
       static std::string get_aor_domain (const std::string & aor);
 
       void update_aor_map (std::map<std::string, std::string> _accounts);
 
-      /* OPAL Methods */
-      void Register (const std::string username,
-                    const std::string host,
-                    const std::string auth_username,
-                    const std::string password,
-                    bool is_enabled,
-                    SIPRegister::CompatibilityModes compat_mode,
-                    unsigned timeout);
+      /* Enable / Disable accounts. The account given as argument
+       * will be updated to reflect the current account state once
+       * the operation has been successful.
+       */
+      void enable_account (Account & account);
+      void disable_account (Account & account);
 
+      /* OPAL Methods */
       void OnRegistrationStatus (const RegistrationStatus & status);
 
       void OnMWIReceived (const PString & party,
@@ -162,6 +157,7 @@ namespace Opal {
       void OnMESSAGECompleted (const SIPMessage::Params & params,
                                SIP_PDU::StatusCodes reason);
 
+      // FIXME: unneeded
       SIPURL GetRegisteredPartyName (const SIPURL & host,
                                     const OpalTransport & transport);
 
@@ -190,6 +186,8 @@ namespace Opal {
       boost::shared_ptr<SIP::Dialect> dialect;
 
       boost::shared_ptr<Ekiga::Settings> settings;
+      const Ekiga::ServiceCore & core;
+      Ekiga::CallProtocolManager::InterfaceList interfaces;
     };
   };
 };


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