[ekiga/ds-opal-refactoring] Opal: Reimplemented call forwarding.



commit 722d1be98c7a578b0b73f4b7c3cb44e3ba4b90b0
Author: Damien Sandras <dsandras seconix com>
Date:   Sat Apr 11 18:13:24 2015 +0200

    Opal: Reimplemented call forwarding.
    
    Call forwarding decisions have been left to CallManager/EndPoints: they
    are protocol dependant.

 lib/engine/components/opal/h323-call-manager.cpp   |   30 ++++++--
 lib/engine/components/opal/h323-call-manager.h     |    3 +-
 lib/engine/components/opal/opal-call-manager.cpp   |   15 +---
 lib/engine/components/opal/opal-call.cpp           |   85 +++++++++++---------
 lib/engine/components/opal/opal-call.h             |   59 +++++++-------
 .../components/opal/process/h323-endpoint.cpp      |   73 ++++++++++-------
 lib/engine/components/opal/process/h323-endpoint.h |   10 +++
 .../components/opal/process/opal-endpoint.cpp      |   10 +-
 lib/engine/components/opal/process/opal-endpoint.h |    6 +-
 .../components/opal/process/sip-endpoint.cpp       |   70 ++++++++++------
 lib/engine/components/opal/process/sip-endpoint.h  |   13 +++
 lib/engine/components/opal/sip-call-manager.cpp    |   26 +++++--
 lib/engine/components/opal/sip-call-manager.h      |    1 +
 lib/engine/protocol/call.h                         |    5 -
 14 files changed, 243 insertions(+), 163 deletions(-)
---
diff --git a/lib/engine/components/opal/h323-call-manager.cpp 
b/lib/engine/components/opal/h323-call-manager.cpp
index ca78709..0043f07 100644
--- a/lib/engine/components/opal/h323-call-manager.cpp
+++ b/lib/engine/components/opal/h323-call-manager.cpp
@@ -54,6 +54,7 @@ Opal::H323::CallManager::CallManager (Ekiga::ServiceCore& _core,
   /* Setup things */
   Ekiga::SettingsCallback setup_cb = boost::bind (&Opal::H323::CallManager::setup, this, _1);
   h323_settings = Ekiga::SettingsPtr (new Ekiga::Settings (H323_SCHEMA, setup_cb));
+  call_forwarding_settings = Ekiga::SettingsPtr (new Ekiga::Settings (CALL_FORWARDING_SCHEMA, setup_cb));
   video_codecs_settings = Ekiga::SettingsPtr (new Ekiga::Settings (VIDEO_CODECS_SCHEMA));
 }
 
@@ -176,10 +177,11 @@ Opal::H323::CallManager::get_dtmf_mode () const
 
 void Opal::H323::CallManager::setup (const std::string & setting)
 {
-  if (setting.empty () || setting == "listen-port") {
+  std::string forward_uri;
 
+  if (setting.empty () || setting == "listen-port")
     set_listen_port (h323_settings->get_int ("listen-port"));
-  }
+
   if (setting.empty () || setting == "maximum-video-tx-bitrate") {
 
     // maximum_video_tx_bitrate is the max video bitrate specified by the user
@@ -189,30 +191,45 @@ void Opal::H323::CallManager::setup (const std::string & setting)
     h323_endpoint.SetInitialBandwidth (OpalBandwidth::Tx, maximum_video_tx_bitrate > 0 ? 
maximum_video_tx_bitrate * 11 : 100000);
     PTRACE (4, "Opal::H323::EndPoint\tSet maximum/initial tx bandwidth to " << maximum_video_tx_bitrate * 
11);
   }
+
   if (setting.empty () || setting == "enable-h245-tunneling") {
 
     h323_endpoint.DisableH245Tunneling (!h323_settings->get_bool ("enable-h245-tunneling"));
     PTRACE (4, "Opal::H323::EndPoint\tH.245 Tunneling: " << h323_settings->get_bool 
("enable-h245-tunneling"));
   }
+
   if (setting.empty () || setting == "enable-early-h245") {
 
     h323_endpoint.DisableH245inSetup (!h323_settings->get_bool ("enable-early-h245"));
     PTRACE (4, "Opal::H323::EndPoint\tEarly H.245: " << h323_settings->get_bool ("enable-early-h245"));
   }
+
   if (setting.empty () || setting == "enable-fast-connect") {
 
     h323_endpoint.DisableFastStart (!h323_settings->get_bool ("enable-fast-connect"));
     PTRACE (4, "Opal::H323::EndPoint\tFast Connect: " << h323_settings->get_bool ("enable-fast-connect"));
   }
+
   if (setting.empty () || setting == "dtmf-mode") {
 
     set_dtmf_mode (h323_settings->get_enum ("dtmf-mode"));
   }
-  if (setting.empty () || setting == "forward-host") {
 
-    std::cout << "FIXME" << std::endl;
-    //h323_endpoint.set_forward_uri (h323_settings->get_string ("forward-host"));
-  }
+  if (setting.empty () || setting == "forward-host")
+    forward_uri = h323_settings->get_string ("forward-host");
+
+  /* Setup the various forwarding targets.
+   * The no answer delay is defined in the opal-call-manager (our parent).
+   */
+  if (setting.empty () || setting == "forward-on-no-anwer")
+    h323_endpoint.SetNoAnswerForwardTarget (call_forwarding_settings->get_bool ("forward-on-no-answer") ? 
forward_uri : "");
+
+  if (setting.empty () || setting == "forward-on-busy")
+    h323_endpoint.SetBusyForwardTarget (call_forwarding_settings->get_bool ("forward-on-busy") ? forward_uri 
: "");
+
+  if (setting.empty () || setting == "always-forward")
+    h323_endpoint.SetUnconditionalForwardTarget (call_forwarding_settings->get_bool ("always-forward") ? 
forward_uri : "");
+
   if (setting.empty () || setting == "video-role") {
 
     /*
@@ -223,6 +240,7 @@ void Opal::H323::CallManager::setup (const std::string & setting)
      */
     std::cout << "FIXME" << std::endl;
   }
+
   if (setting.empty () || setting == "enable-h239") {
 
     h323_endpoint.SetDefaultH239Control(h323_settings->get_bool ("enable-h239"));
diff --git a/lib/engine/components/opal/h323-call-manager.h b/lib/engine/components/opal/h323-call-manager.h
index ed5413a..bfbab20 100644
--- a/lib/engine/components/opal/h323-call-manager.h
+++ b/lib/engine/components/opal/h323-call-manager.h
@@ -88,10 +88,9 @@ namespace Opal {
   private:
 
       Ekiga::SettingsPtr h323_settings;
+      Ekiga::SettingsPtr call_forwarding_settings;
       Ekiga::SettingsPtr video_codecs_settings;
-
       Opal::H323::EndPoint& h323_endpoint;
-
       std::string protocol_name;
     };
   };
diff --git a/lib/engine/components/opal/opal-call-manager.cpp 
b/lib/engine/components/opal/opal-call-manager.cpp
index e3d7eff..46697bd 100644
--- a/lib/engine/components/opal/opal-call-manager.cpp
+++ b/lib/engine/components/opal/opal-call-manager.cpp
@@ -76,13 +76,13 @@ void Opal::CallManager::hang_up ()
 
 void Opal::CallManager::set_reject_delay (unsigned delay)
 {
-  endpoint.set_reject_delay (delay);
+  endpoint.SetNoAnswerDelay (delay);
 }
 
 
 unsigned Opal::CallManager::get_reject_delay () const
 {
-  return endpoint.get_reject_delay ();
+  return endpoint.GetNoAnswerDelay ();
 }
 
 
@@ -201,20 +201,11 @@ void Opal::CallManager::setup (const std::string & setting)
     endpoint.SetMediaTypeOfService (protocols_settings->get_int ("rtp-tos-field"));
 
   if (setting.empty () || setting == "no-answer-timeout")
-    endpoint.set_reject_delay (call_options_settings->get_int ("no-answer-timeout"));
+    set_reject_delay (call_options_settings->get_int ("no-answer-timeout"));
 
   if (setting.empty () || setting == "auto-answer")
     endpoint.set_auto_answer (call_options_settings->get_bool ("auto-answer"));
 
-  if (setting.empty () || setting == "forward-on-no-anwer")
-    endpoint.set_forward_on_no_answer (call_forwarding_settings->get_bool ("forward-on-no-answer"));
-
-  if (setting.empty () || setting == "forward-on-busy")
-    endpoint.set_forward_on_busy (call_forwarding_settings->get_bool ("forward-on-busy"));
-
-  if (setting.empty () || setting == "always-forward")
-    endpoint.set_unconditional_forward (call_forwarding_settings->get_bool ("always-forward"));
-
   if (setting.empty () || setting == "full-name")
     set_display_name (personal_data_settings->get_string ("full-name"));
 
diff --git a/lib/engine/components/opal/opal-call.cpp b/lib/engine/components/opal/opal-call.cpp
index ad6ac49..19f735b 100644
--- a/lib/engine/components/opal/opal-call.cpp
+++ b/lib/engine/components/opal/opal-call.cpp
@@ -73,19 +73,22 @@ strip_special_chars (std::string& str, char* special_chars, bool start)
 
 boost::shared_ptr<Opal::Call>
 Opal::Call::create (EndPoint& _manager,
-                    const std::string & uri)
+                    const std::string & uri,
+                    const unsigned no_answer_delay)
 {
-  return boost::shared_ptr<Opal::Call> (new Opal::Call (_manager, uri));
+  return boost::shared_ptr<Opal::Call> (new Opal::Call (_manager, uri, no_answer_delay));
 }
 
 
 Opal::Call::Call (Opal::EndPoint& _manager,
-                 const std::string& uri)
-  : OpalCall (_manager), Ekiga::Call (), remote_uri (uri),
-    call_setup(false), outgoing(false)
+                  const std::string& _uri,
+                  const unsigned _no_answer_delay)
+  : OpalCall (_manager),
+    Ekiga::Call (),
+    remote_uri (_uri),
+    call_setup (false),
+    outgoing (false)
 {
-  NoAnswerTimer.SetNotifier (PCREATE_NOTIFIER (OnNoAnswerTimeout));
-
   add_action (Ekiga::ActionPtr (new Ekiga::Action ("hangup", _("Hangup"),
                                                    boost::bind (&Call::hang_up, this))));
   if (!is_outgoing () && !IsEstablished ()) {
@@ -93,6 +96,10 @@ Opal::Call::Call (Opal::EndPoint& _manager,
                                                      boost::bind (&Call::answer, this))));
     add_action (Ekiga::ActionPtr (new Ekiga::Action ("reject", _("Reject"),
                                                      boost::bind (&Call::hang_up, this))));
+
+    noAnswerTimer.SetNotifier (PCREATE_NOTIFIER (OnNoAnswerTimeout));
+    if (_no_answer_delay > 0)
+      noAnswerTimer.SetInterval (0, _no_answer_delay);
   }
 }
 
@@ -150,7 +157,7 @@ Opal::Call::transfer ()
 bool
 Opal::Call::transfer (std::string uri)
 {
-  PSafePtr<OpalConnection> connection = get_remote_connection ();
+  PSafePtr<OpalConnection> connection = GetConnection ();
   if (connection != NULL)
     return connection->TransferConnection (uri);
 
@@ -189,7 +196,7 @@ void
 Opal::Call::toggle_hold ()
 {
   bool on_hold = false;
-  PSafePtr<OpalConnection> connection = get_remote_connection ();
+  PSafePtr<OpalConnection> connection = GetConnection ();
   if (connection != NULL) {
 
     on_hold = connection->IsOnHold (false);
@@ -207,7 +214,7 @@ Opal::Call::toggle_stream_pause (StreamType type)
 
   bool paused = false;
 
-  PSafePtr<OpalConnection> connection = get_remote_connection ();
+  PSafePtr<OpalConnection> connection = GetConnection ();
   if (connection != NULL) {
 
     stream = connection->GetMediaStream ((type == Audio) ? OpalMediaType::Audio () : OpalMediaType::Video 
(), false);
@@ -230,24 +237,17 @@ Opal::Call::toggle_stream_pause (StreamType type)
 void
 Opal::Call::send_dtmf (const char dtmf)
 {
-  PSafePtr<OpalConnection> connection = get_remote_connection ();
+  PSafePtr<OpalConnection> connection = GetConnection ();
   if (connection != NULL) {
     connection->SendUserInputTone (dtmf, 180);
   }
 }
 
 
-void Opal::Call::set_no_answer_forward (unsigned delay, const std::string & uri)
-{
-  forward_uri = uri;
-
-  NoAnswerTimer.SetInterval (0, std::min (delay, (unsigned) 299));
-}
-
-
-void Opal::Call::set_reject_delay (unsigned delay)
+void
+Opal::Call::set_forward_target (const std::string & _forward_uri)
 {
-  NoAnswerTimer.SetInterval (0, std::min (delay, (unsigned) 299));
+  forward_uri = _forward_uri;
 }
 
 
@@ -314,7 +314,7 @@ Opal::Call::get_start_time () const
 const RTCPStatistics &
 Opal::Call::get_statistics ()
 {
-  PSafePtr<OpalConnection> connection = get_remote_connection ();
+  PSafePtr<OpalConnection> connection = GetConnection ();
   if (connection == NULL)
     return statistics;
 
@@ -452,13 +452,31 @@ Opal::Call::parse_info (OpalConnection & connection)
 }
 
 
+PSafePtr<OpalConnection>
+Opal::Call::GetConnection ()
+{
+  PSafePtr<OpalConnection> connection;
+  for (PSafePtr<OpalConnection> iter (connectionsActive, PSafeReference); iter != NULL; ++iter) {
+
+    if (PSafePtrCast<OpalConnection, OpalPCSSConnection> (iter) == NULL) {
+      connection = iter;
+      if (!connection.SetSafetyMode (PSafeReadWrite))
+        connection.SetNULL();
+      break;
+    }
+  }
+
+  return connection;
+}
+
+
 PBoolean
 Opal::Call::OnEstablished (OpalConnection & connection)
 {
   OpalRTPSession *session = NULL;
   OpalMediaStreamPtr stream;
 
-  NoAnswerTimer.Stop (false);
+  noAnswerTimer.Stop (false);
 
   if (!PIsDescendant(&connection, OpalPCSSConnection)) {
 
@@ -512,11 +530,7 @@ Opal::Call::OnCleared ()
 {
   std::string reason;
 
-  NoAnswerTimer.Stop (false);
-
-  // TODO find a better way than that
-  while (!call_setup)
-    PThread::Current ()->Sleep (100);
+  noAnswerTimer.Stop (false);
 
   OpalCall::OnCleared ();
 
@@ -719,15 +733,12 @@ void
 Opal::Call::OnNoAnswerTimeout (PTimer &,
                                INT)
 {
-  if (!is_outgoing ()) {
-
-    if (!forward_uri.empty ()) {
+  if (!forward_uri.empty ()) {
 
-      PSafePtr<OpalConnection> connection = get_remote_connection ();
-      if (connection != NULL)
-        connection->ForwardCall (forward_uri);
-    }
-    else
-      Clear (OpalConnection::EndedByNoAnswer);
+    PSafePtr<OpalConnection> connection = GetConnection ();
+    if (connection != NULL)
+      connection->ForwardCall (forward_uri);
   }
+  else
+    Clear (OpalConnection::EndedByNoAnswer);
 }
diff --git a/lib/engine/components/opal/opal-call.h b/lib/engine/components/opal/opal-call.h
index 9fcd23e..2d14232 100644
--- a/lib/engine/components/opal/opal-call.h
+++ b/lib/engine/components/opal/opal-call.h
@@ -62,8 +62,13 @@ namespace Opal {
   {
 
 private:
+    /* This constructor is private and should not be called
+     * directly because of DynamicObject.
+     */
     Call (EndPoint& _manager,
-          const std::string & uri);
+          const std::string & uri,
+          const unsigned no_answer_delay);
+
 
 public:
     ~Call ();
@@ -71,12 +76,20 @@ public:
     /*
      * This method will create and return an shared_ptr to the object.
      *
-     * Classical constructors should not be used as we need to have
-     * a shared_ptr to the object as soon as possible to be able to
-     * use shared_from_this from the beginning.
+     * Classical constructors should not be used as we need to have a
+     * shared_ptr to the object as soon as possible to be able to use
+     * shared_from_this from the beginning.
+     *
+     * @param The Opal::EndPoint
+     * @param The remote URI (if any)
+     * @param The delay after which the call should be rejected
+     *        or forwarded if a forward URI has been setup with
+     *        set_forward_target.
      */
     static boost::shared_ptr<Call> create (EndPoint& _manager,
-                                           const std::string & uri);
+                                           const std::string & uri,
+                                           const unsigned no_answer_delay);
+
 
     /*
      * Call Management
@@ -100,6 +113,7 @@ public:
      */
     bool transfer (std::string uri);
 
+
     /** Put the call on hold or retrieve it
      */
     void toggle_hold ();
@@ -114,16 +128,12 @@ public:
      */
     void send_dtmf (const char dtmf);
 
-    /** Forward an incoming call after the given delay
-     * @param delay the delay after which we forward
-     * @param uri is the uri to forward to
-     */
-    void set_no_answer_forward (unsigned delay, const std::string & uri);
 
-    /** Reject an incoming call after the given delay
-     * @param delay the delay after which reject the call
+    /** Set forward target (if applicable)
+     * @param The forward target to which the call should be forwarded
+     *        after no_answer_delay.
      */
-    void set_reject_delay (unsigned delay);
+    void set_forward_target (const std::string & forward_uri);
 
 
     /*
@@ -189,6 +199,7 @@ public:
 
     void DoSetUp (OpalConnection & connection);
 
+
 private:
 
     PBoolean OnEstablished (OpalConnection & connection);
@@ -212,25 +223,8 @@ private:
 
     void parse_info (OpalConnection & connection);
 
-    PSafePtr<OpalConnection> get_remote_connection ()
-      {
-        PSafePtr<OpalConnection> connection;
-        for (PSafePtr<OpalConnection> iterConn (connectionsActive, PSafeReference); iterConn != NULL; 
++iterConn) {
-          if (PSafePtrCast<OpalConnection, OpalPCSSConnection> (iterConn) == NULL) {
-            connection = iterConn;
-            if (!connection.SetSafetyMode(PSafeReadWrite))
-              connection.SetNULL();
-            break;
-          }
-        }
-        return connection;
-      }
+    PSafePtr<OpalConnection> GetConnection ();
 
-    /*
-     *
-     */
-    PDECLARE_NOTIFIER(PTimer, Opal::Call, OnNoAnswerTimeout);
-    PTimer NoAnswerTimer;
 
     /*
      * Variables
@@ -250,6 +244,9 @@ private:
     PTime start_time;
     RTCPStatistics statistics;
     bool auto_answer;
+
+    PDECLARE_NOTIFIER(PTimer, Opal::Call, OnNoAnswerTimeout);
+    PTimer noAnswerTimer;
   };
 };
 
diff --git a/lib/engine/components/opal/process/h323-endpoint.cpp 
b/lib/engine/components/opal/process/h323-endpoint.cpp
index f7fba12..ec4ceac 100644
--- a/lib/engine/components/opal/process/h323-endpoint.cpp
+++ b/lib/engine/components/opal/process/h323-endpoint.cpp
@@ -204,6 +204,27 @@ Opal::H323::EndPoint::DisableAccount (Account& account)
 }
 
 
+void
+Opal::H323::EndPoint::SetNoAnswerForwardTarget (const PString & _party)
+{
+  noAnswerForwardParty = _party;
+}
+
+
+void
+Opal::H323::EndPoint::SetUnconditionalForwardTarget (const PString & _party)
+{
+  unconditionalForwardParty = _party;
+}
+
+
+void
+Opal::H323::EndPoint::SetBusyForwardTarget (const PString & _party)
+{
+  busyForwardParty = _party;
+}
+
+
 bool
 Opal::H323::EndPoint::UseGatekeeper (const PString & address,
                                      const PString & domain,
@@ -248,45 +269,37 @@ Opal::H323::EndPoint::OnIncomingConnection (OpalConnection & connection,
                                            G_GNUC_UNUSED unsigned options,
                                            G_GNUC_UNUSED OpalConnection::StringOptions *stroptions)
 {
-  bool busy = false;
-
   PTRACE (3, "Opal::H323::EndPoint\tIncoming connection");
 
   if (!H323EndPoint::OnIncomingConnection (connection, options, stroptions))
     return false;
 
-  for (PSafePtr<OpalConnection> conn(connectionsActive, PSafeReference); conn != NULL; ++conn) {
-    if (conn->GetCall().GetToken() != connection.GetCall().GetToken() && !conn->IsReleased ())
-      busy = true;
+  /* Unconditional call forward? */
+  if (!unconditionalForwardParty.IsEmpty ()) {
+    PTRACE (3, "Opal::H323::EndPoint\tIncoming connection forwarded to " << busyForwardParty << " 
(Unconditional)");
+    connection.ForwardCall (unconditionalForwardParty);
+    return false;
   }
 
-  std::cout << "FIXME" << std::endl;
-
-  /*
-  if (!forward_uri.empty () && manager.get_unconditional_forward ())
-    connection.ForwardCall (forward_uri);
-  else if (busy) {
-
-    if (!forward_uri.empty () && manager.get_forward_on_busy ())
-      connection.ForwardCall (forward_uri);
-    else {
-      connection.ClearCall (OpalConnection::EndedByLocalBusy);
+  /* Busy call forward? */
+  for (PSafePtr<OpalConnection> conn(connectionsActive, PSafeReference); conn != NULL; ++conn) {
+    if (conn->GetCall().GetToken() != connection.GetCall().GetToken() && !conn->IsReleased ()) {
+      if (!busyForwardParty.IsEmpty ()) {
+        PTRACE (3, "Opal::H323::EndPoint\tIncoming connection forwarded to " << busyForwardParty << " 
(busy)");
+        connection.ForwardCall (busyForwardParty);
+      }
+      else {
+        PTRACE (3, "Opal::H323::EndPoint\tIncoming connection rejected (busy)");
+        connection.ClearCall (OpalConnection::EndedByLocalBusy);
+      }
+      return false;
     }
   }
-  else {
-
-    Opal::Call *call = dynamic_cast<Opal::Call *> (&connection.GetCall ());
-    if (call) {
 
-      if (!forward_uri.empty () && manager.get_forward_on_no_answer ())
-        call->set_no_answer_forward (manager.get_reject_delay (), forward_uri);
-      else
-        call->set_reject_delay (manager.get_reject_delay ());
-    }
+  /* No Answer Call Forward or Reject */
+  Opal::Call *call = dynamic_cast<Opal::Call *> (&connection.GetCall ());
+  if (call)
+    call->set_forward_target (noAnswerForwardParty);
 
-    return H323EndPoint::OnIncomingConnection (connection, options, stroptions);
-  }
-  */
-
-  return false;
+  return true;
 }
diff --git a/lib/engine/components/opal/process/h323-endpoint.h 
b/lib/engine/components/opal/process/h323-endpoint.h
index 7990a22..e530a38 100644
--- a/lib/engine/components/opal/process/h323-endpoint.h
+++ b/lib/engine/components/opal/process/h323-endpoint.h
@@ -82,6 +82,12 @@ namespace Opal {
 
       void DisableAccount (Account & account);
 
+      void SetNoAnswerForwardTarget (const PString & party);
+
+      void SetUnconditionalForwardTarget (const PString & party);
+
+      void SetBusyForwardTarget (const PString & party);
+
       bool UseGatekeeper (const PString & address = PString::Empty (),
                           const PString & domain = PString::Empty (),
                           const PString & iface = PString::Empty ());
@@ -99,6 +105,10 @@ namespace Opal {
       PString gk_name;
 
       const Ekiga::ServiceCore & core;
+
+      PString noAnswerForwardParty;
+      PString unconditionalForwardParty;
+      PString busyForwardParty;
     };
   };
 };
diff --git a/lib/engine/components/opal/process/opal-endpoint.cpp 
b/lib/engine/components/opal/process/opal-endpoint.cpp
index 2e9d564..f5099e9 100644
--- a/lib/engine/components/opal/process/opal-endpoint.cpp
+++ b/lib/engine/components/opal/process/opal-endpoint.cpp
@@ -311,15 +311,15 @@ bool Opal::EndPoint::GetSilenceDetection () const
 }
 
 
-void Opal::EndPoint::set_reject_delay (unsigned delay)
+void Opal::EndPoint::SetNoAnswerDelay (unsigned delay)
 {
-  reject_delay = std::max ((unsigned) 5, delay);
+  noAnswerDelay = std::max ((unsigned int) 0, delay);
 }
 
 
-unsigned Opal::EndPoint::get_reject_delay () const
+unsigned Opal::EndPoint::GetNoAnswerDelay () const
 {
-  return reject_delay;
+  return noAnswerDelay;
 }
 
 
@@ -549,7 +549,7 @@ void Opal::EndPoint::GetVideoOptions (Opal::EndPoint::VideoOptions & options) co
 OpalCall *Opal::EndPoint::CreateCall (void *uri)
 {
   boost::shared_ptr<Ekiga::CallCore> call_core = core.get<Ekiga::CallCore> ("call-core");
-  boost::shared_ptr<Opal::Call> call = Opal::Call::create (*this, uri ? (const char*) uri : std::string ());
+  boost::shared_ptr<Opal::Call> call = Opal::Call::create (*this, uri ? (const char*) uri : std::string (), 
noAnswerDelay);
 
   Ekiga::Runtime::run_in_main (boost::bind (&Ekiga::CallCore::add_call, call_core, call));
 
diff --git a/lib/engine/components/opal/process/opal-endpoint.h 
b/lib/engine/components/opal/process/opal-endpoint.h
index d0aa5db..41f6ce5 100644
--- a/lib/engine/components/opal/process/opal-endpoint.h
+++ b/lib/engine/components/opal/process/opal-endpoint.h
@@ -96,8 +96,8 @@ public:
     void SetSilenceDetection (bool enabled);
     bool GetSilenceDetection () const;
 
-    void set_reject_delay (unsigned delay);
-    unsigned get_reject_delay () const;
+    void SetNoAnswerDelay (unsigned delay);
+    unsigned GetNoAnswerDelay () const;
 
     void set_auto_answer (bool enabled);
     bool get_auto_answer () const;
@@ -168,7 +168,7 @@ private:
     unsigned int patience;
 
     std::string stun_server;
-    unsigned reject_delay;
+    unsigned noAnswerDelay;
     bool forward_on_busy;
     bool unconditional_forward;
     bool forward_on_no_answer;
diff --git a/lib/engine/components/opal/process/sip-endpoint.cpp 
b/lib/engine/components/opal/process/sip-endpoint.cpp
index a51b1e7..2081c1b 100644
--- a/lib/engine/components/opal/process/sip-endpoint.cpp
+++ b/lib/engine/components/opal/process/sip-endpoint.cpp
@@ -121,7 +121,7 @@ Opal::Sip::EndPoint::EndPoint (Opal::EndPoint & _endpoint,
   GetManager ().AddRouteEntry("sip:.* = pc:*");
   GetManager ().AddRouteEntry("pc:.* = sip:<da>");
 
-  /* NAT Binding */
+  /* Keepalive */
   PTimeInterval timeout;
   KeepAliveType type;
   GetKeepAlive (timeout, type);
@@ -237,6 +237,27 @@ Opal::Sip::EndPoint::DisableAccount (Account & account)
 
 
 void
+Opal::Sip::EndPoint::SetNoAnswerForwardTarget (const PString & _party)
+{
+  noAnswerForwardParty = _party;
+}
+
+
+void
+Opal::Sip::EndPoint::SetUnconditionalForwardTarget (const PString & _party)
+{
+  unconditionalForwardParty = _party;
+}
+
+
+void
+Opal::Sip::EndPoint::SetBusyForwardTarget (const PString & _party)
+{
+  busyForwardParty = _party;
+}
+
+
+void
 Opal::Sip::EndPoint::OnRegistrationStatus (const RegistrationStatus & status)
 {
   std::string info;
@@ -548,43 +569,40 @@ Opal::Sip::EndPoint::OnMWIReceived (const PString & party,
 bool
 Opal::Sip::EndPoint::OnIncomingConnection (OpalConnection &connection,
                                           unsigned options,
-                                          OpalConnection::StringOptions * stroptions)
+                                          OpalConnection::StringOptions *stroptions)
 {
-  bool busy = false;
   PTRACE (3, "Opal::Sip::EndPoint\tIncoming connection");
 
   if (!SIPEndPoint::OnIncomingConnection (connection, options, stroptions))
     return false;
 
-  for (PSafePtr<OpalConnection> conn(connectionsActive, PSafeReference); conn != NULL; ++conn) {
-    if (conn->GetCall().GetToken() != connection.GetCall().GetToken() && !conn->IsReleased ())
-      busy = true;
+  /* Unconditional call forward? */
+  if (!unconditionalForwardParty.IsEmpty ()) {
+    PTRACE (3, "Opal::Sip::EndPoint\tIncoming connection forwarded to " << busyForwardParty << " 
(Unconditional)");
+    connection.ForwardCall (unconditionalForwardParty);
+    return false;
   }
-  std::cout << "FIXME" << std::endl << std::flush;
-  /*
-
-  if (!forward_uri.empty () && manager.get_unconditional_forward ())
-    connection.ForwardCall (forward_uri);
-  else if (busy) {
 
-    if (!forward_uri.empty () && manager.get_forward_on_busy ())
-      connection.ForwardCall (forward_uri);
-    else {
-      connection.ClearCall (OpalConnection::EndedByLocalBusy);
+  /* Busy call forward? */
+  for (PSafePtr<OpalConnection> conn(connectionsActive, PSafeReference); conn != NULL; ++conn) {
+    if (conn->GetCall().GetToken() != connection.GetCall().GetToken() && !conn->IsReleased ()) {
+      if (!busyForwardParty.IsEmpty ()) {
+        PTRACE (3, "Opal::Sip::EndPoint\tIncoming connection forwarded to " << busyForwardParty << " 
(busy)");
+        connection.ForwardCall (busyForwardParty);
+      }
+      else {
+        PTRACE (3, "Opal::Sip::EndPoint\tIncoming connection rejected (busy)");
+        connection.ClearCall (OpalConnection::EndedByLocalBusy);
+      }
+      return false;
     }
   }
-  else {
 
-    Opal::Call *call = dynamic_cast<Opal::Call *> (&connection.GetCall ());
-    if (call) {
+  /* No Answer Call Forward or Reject */
+  Opal::Call *call = dynamic_cast<Opal::Call *> (&connection.GetCall ());
+  if (call)
+    call->set_forward_target (noAnswerForwardParty);
 
-      if (!forward_uri.empty () && manager.get_forward_on_no_answer ())
-        call->set_no_answer_forward (manager.get_reject_delay (), forward_uri);
-      else // Pending
-        call->set_reject_delay (manager.get_reject_delay ());
-    }
-  }
-*/
   return true;
 }
 
diff --git a/lib/engine/components/opal/process/sip-endpoint.h 
b/lib/engine/components/opal/process/sip-endpoint.h
index 908cfb4..7aae442 100644
--- a/lib/engine/components/opal/process/sip-endpoint.h
+++ b/lib/engine/components/opal/process/sip-endpoint.h
@@ -70,6 +70,7 @@ namespace Opal {
 
       bool SetUpCall (const std::string & uri);
 
+
       /* Chat subsystem */
       bool send_message (const std::string & uri,
                          const Ekiga::Message::payload_type payload);
@@ -81,6 +82,7 @@ namespace Opal {
       // the parameters are the aor and the info
       boost::signals2::signal<void(std::string, std::string)> mwi_event;
 
+
       /* Enable / Disable accounts. The account given as argument
        * will be updated to reflect the current account state once
        * the operation has been successful.
@@ -89,6 +91,13 @@ namespace Opal {
 
       void DisableAccount (Account & account);
 
+      void SetNoAnswerForwardTarget (const PString & party);
+
+      void SetUnconditionalForwardTarget (const PString & party);
+
+      void SetBusyForwardTarget (const PString & party);
+
+
     private:
       /* OPAL Methods */
       void OnRegistrationStatus (const RegistrationStatus & status);
@@ -109,6 +118,10 @@ namespace Opal {
                                SIP_PDU::StatusCodes reason);
 
       const Ekiga::ServiceCore & core;
+
+      PString noAnswerForwardParty;
+      PString unconditionalForwardParty;
+      PString busyForwardParty;
     };
   };
 };
diff --git a/lib/engine/components/opal/sip-call-manager.cpp b/lib/engine/components/opal/sip-call-manager.cpp
index d058e22..0a0ff33 100644
--- a/lib/engine/components/opal/sip-call-manager.cpp
+++ b/lib/engine/components/opal/sip-call-manager.cpp
@@ -54,6 +54,7 @@ Opal::Sip::CallManager::CallManager (Ekiga::ServiceCore& _core,
   /* Setup things */
   Ekiga::SettingsCallback setup_cb = boost::bind (&Opal::Sip::CallManager::setup, this, _1);
   sip_settings = Ekiga::SettingsPtr (new Ekiga::Settings (SIP_SCHEMA, setup_cb));
+  call_forwarding_settings = Ekiga::SettingsPtr (new Ekiga::Settings (CALL_FORWARDING_SCHEMA, setup_cb));
 }
 
 
@@ -164,28 +165,41 @@ Opal::Sip::CallManager::get_dtmf_mode () const
 
 void Opal::Sip::CallManager::setup (const std::string & setting)
 {
+  std::string forward_uri;
+
   if (setting.empty () || setting == "listen-port")  {
     set_listen_port (sip_settings->get_int ("listen-port"));
   }
+
   if (setting.empty () || setting == "keepalive-interval")  {
     int delay = sip_settings->get_int ("keepalive-interval");
     PTRACE (4, "Opal::Sip::CallManager\tKeepalive interval set to " << delay);
     sip_endpoint.SetKeepAlive (PTimeInterval (0, delay), SIPEndPoint::KeepAliveByOPTION);
   }
+
   if (setting.empty () || setting == "outbound-proxy-host")  {
     std::string uri = sip_settings->get_string ("outbound-proxy-host");
     PTRACE (4, "Opal::Sip::CallManager\tSet outbound proxy to " << uri);
     sip_endpoint.SetProxy (SIPURL (uri));
   }
 
-  if (setting.empty () || setting == "dtmf-mode")  {
+  if (setting.empty () || setting == "dtmf-mode")
     set_dtmf_mode (sip_settings->get_enum ("dtmf-mode"));
-  }
 
-  if (setting.empty () || setting == "forward-host")  {
-    std::cout << "FIXME" << std::endl;
-    //sip_endpoint.set_forward_uri (sip_settings->get_string ("forward-host"));
-  }
+  if (setting.empty () || setting == "forward-host")
+    forward_uri = sip_settings->get_string ("forward-host");
+
+  /* Setup the various forwarding targets.
+   * The no answer delay is defined in the opal-call-manager (our parent).
+   */
+  if (setting.empty () || setting == "forward-on-no-anwer")
+    sip_endpoint.SetNoAnswerForwardTarget (call_forwarding_settings->get_bool ("forward-on-no-answer") ? 
forward_uri : "");
+
+  if (setting.empty () || setting == "forward-on-busy")
+    sip_endpoint.SetBusyForwardTarget (call_forwarding_settings->get_bool ("forward-on-busy") ? forward_uri 
: "");
+
+  if (setting.empty () || setting == "always-forward")
+    sip_endpoint.SetUnconditionalForwardTarget (call_forwarding_settings->get_bool ("always-forward") ? 
forward_uri : "");
 
   Opal::CallManager::setup (setting);
 }
diff --git a/lib/engine/components/opal/sip-call-manager.h b/lib/engine/components/opal/sip-call-manager.h
index 303fee8..f2a8be3 100644
--- a/lib/engine/components/opal/sip-call-manager.h
+++ b/lib/engine/components/opal/sip-call-manager.h
@@ -88,6 +88,7 @@ namespace Opal {
   private:
 
       Ekiga::SettingsPtr sip_settings;
+      Ekiga::SettingsPtr call_forwarding_settings;
       Opal::Sip::EndPoint& sip_endpoint;
       std::string protocol_name;
     };
diff --git a/lib/engine/protocol/call.h b/lib/engine/protocol/call.h
index 8201c71..970dbdf 100644
--- a/lib/engine/protocol/call.h
+++ b/lib/engine/protocol/call.h
@@ -99,11 +99,6 @@ namespace Ekiga
        */
       virtual void send_dtmf (const char dtmf) = 0;
 
-      /** Reject an incoming call after the given delay
-       * @param delay the delay after which reject the call
-       */
-      virtual void set_reject_delay (unsigned delay) = 0;
-
 
       /*
        * Call Information


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