enclosed find diff to 1.4 sbc app that adds simultaneous call control
via profile vars:

enable_call_control=yes
call_control_uuid=$fu
call_control_max_calls=$P(max_calls)

it is ok with me to change code to utilize a general purpose call
control api once available.

one thing i feel uncomfortable is cancel handling.  i added to
onSipRequest:

if (req.method == "CANCEL") decCallControlCalls();

what if caller sends many cancels back-to-back?  will each of them cause
decCallControlCalls() call?  if so, how to avoid it?

-- juha

diff -c -r /usr/src/orig/sems/apps/sbc//SBCCallProfile.cpp ./SBCCallProfile.cpp
*** /usr/src/orig/sems/apps/sbc//SBCCallProfile.cpp     2011-09-17 
14:08:27.000000000 +0300
--- ./SBCCallProfile.cpp        2011-09-17 13:43:05.000000000 +0300
***************
*** 123,128 ****
--- 123,132 ----
    prepaid_uuid = cfg.getParameter("prepaid_uuid");
    prepaid_acc_dest = cfg.getParameter("prepaid_acc_dest");
  
+   call_control_enabled = cfg.getParameter("enable_call_control", "no") == 
"yes";
+   call_control_uuid = cfg.getParameter("call_control_uuid");
+   call_control_max_calls = cfg.getParameter("call_control_max_calls");
+ 
    // check for acc module if configured statically
    if (prepaid_enabled &&
        (prepaid_accmodule.find('$') == string::npos) &&
***************
*** 238,243 ****
--- 242,252 ----
        INFO("SBC:                    uuid       = '%s'\n", 
prepaid_uuid.c_str());
        INFO("SBC:                    acc_dest   = '%s'\n", 
prepaid_acc_dest.c_str());
      }
+     INFO("SBC:      call_control %sabled\n", call_control_enabled?"en":"dis");
+     if (call_control_enabled) {
+       INFO("SBC:                    uuid       = '%s'\n", 
call_control_uuid.c_str());
+       INFO("SBC:                    max_calls  = '%s'\n", 
call_control_max_calls.c_str());
+     }
      if (reply_translations.size()) {
        string reply_trans_codes;
        for(map<unsigned int, std::pair<unsigned int, string> >::iterator it=
***************
*** 277,282 ****
--- 286,292 ----
      auth_enabled == rhs.auth_enabled &&
      call_timer_enabled == rhs.call_timer_enabled &&
      prepaid_enabled == rhs.prepaid_enabled &&
+     call_control_enabled == rhs.call_control_enabled &&
      reply_translations == rhs.reply_translations &&
      append_headers == rhs.append_headers &&
      refuse_with == rhs.refuse_with &&
***************
*** 304,309 ****
--- 314,324 ----
        prepaid_uuid == rhs.prepaid_uuid &&
        prepaid_acc_dest == rhs.prepaid_acc_dest;
    }
+   if (call_control_enabled) {
+     res = res &&
+       call_control_uuid == rhs.call_control_uuid &&
+       call_control_max_calls == rhs.call_control_max_calls;
+   }
  
    return res;
  }
***************
*** 346,351 ****
--- 361,369 ----
    res += "prepaid_accmodule:    " + prepaid_accmodule + "\n";
    res += "prepaid_uuid:         " + prepaid_uuid + "\n";
    res += "prepaid_acc_dest:     " + prepaid_acc_dest + "\n";
+   res += "call_control_enabled: " + 
string(call_control_enabled?"true":"false") + "\n";
+   res += "call_control_uuid:    " + call_control_uuid + "\n";
+   res += "call_control_max_calls:     " + call_control_max_calls + "\n";
    res += "rtprelay_enabled:     " + string(rtprelay_enabled?"true":"false") + 
"\n";
    res += "force_symmetric_rtp:  " + force_symmetric_rtp;
    res += "msgflags_symmetric_rtp: " + 
string(msgflags_symmetric_rtp?"true":"false") + "\n";
diff -c -r /usr/src/orig/sems/apps/sbc//SBCCallProfile.h ./SBCCallProfile.h
*** /usr/src/orig/sems/apps/sbc//SBCCallProfile.h       2011-09-17 
14:08:27.000000000 +0300
--- ./SBCCallProfile.h  2011-09-17 12:00:23.000000000 +0300
***************
*** 82,87 ****
--- 82,92 ----
    string prepaid_uuid;
    string prepaid_acc_dest;
  
+   bool call_control_enabled;
+   string call_control_uuid;
+   string call_control_max_calls;
+   unsigned short call_control_max_calls_i;
+ 
    map<unsigned int, std::pair<unsigned int, string> > reply_translations;
  
    string append_headers;
***************
*** 105,110 ****
--- 110,116 ----
      auth_enabled(false),
      call_timer_enabled(false),
      prepaid_enabled(false),
+     call_control_enabled(false),
      rtprelay_enabled(false)
  
    { }
diff -c -r /usr/src/orig/sems/apps/sbc//SBC.cpp ./SBC.cpp
*** /usr/src/orig/sems/apps/sbc//SBC.cpp        2011-09-17 14:08:27.000000000 
+0300
--- ./SBC.cpp   2011-09-17 14:04:05.000000000 +0300
***************
*** 53,58 ****
--- 53,61 ----
  AmSessionEventHandlerFactory* SBCFactory::session_timer_fact = NULL;
  RegexMapper SBCFactory::regex_mappings;
  
+ static map <string, unsigned short> call_control_calls;
+ static AmMutex call_control_calls_mut;
+ 
  EXPORT_MODULE_FACTORY(SBCFactory);
  DEFINE_MODULE_INSTANCE(SBCFactory, MOD_NAME);
  
***************
*** 697,702 ****
--- 700,751 ----
      }
    }
  
+   if (call_profile.call_control_enabled) {
+       unsigned int call_control_max_calls_i;
+       call_profile.call_control_uuid =
+         replaceParameters(call_profile.call_control_uuid,
+                           "call_control_uuid", REPLACE_VALS);
+       if (!call_profile.call_control_max_calls.empty()) {
+         call_profile.call_control_max_calls =
+             replaceParameters(call_profile.call_control_max_calls,
+                               "call_control_max_calls", REPLACE_VALS);
+         if (str2i(call_profile.call_control_max_calls,
+                   call_control_max_calls_i)) {
+             ERROR("call_control_max_calls '%s' not understood\n",
+                   call_profile.call_control_max_calls.c_str());
+             throw AmSession::Exception(500, SIP_REPLY_SERVER_INTERNAL_ERROR);
+         }
+         if (call_control_max_calls_i > 255) {
+             ERROR("call_control_max_calls value '%u' too large\n",
+                   call_control_max_calls_i);
+             throw AmSession::Exception(500, SIP_REPLY_SERVER_INTERNAL_ERROR);
+         }
+       } else {
+         call_control_max_calls_i = 1;
+       }
+       call_profile.call_control_max_calls_i = call_control_max_calls_i;
+       INFO("set call_control_max_calls to '%u'\n", call_control_max_calls_i);
+       call_control_calls_mut.lock();
+       map<string, unsigned short>::iterator it = 
+         call_control_calls.find(call_profile.call_control_uuid);
+       if (it == call_control_calls.end()) {
+         INFO("call_control call count for '%s' not found\n",
+              call_profile.call_control_uuid.c_str());
+         call_control_calls[call_profile.call_control_uuid] = 1;
+       } else {
+         if (it->second >= call_control_max_calls_i) {
+             call_control_calls_mut.unlock();
+             throw AmSession::Exception(402, "Too Many Simultaneous Calls");
+         } else {
+             call_control_calls[call_profile.call_control_uuid]++;
+         }
+       }
+       INFO("call_control active calls for uuid '%s' is '%u'\n",
+          call_profile.call_control_uuid.c_str(),
+          call_control_calls[call_profile.call_control_uuid]);
+       call_control_calls_mut.unlock();
+   }
+ 
  #undef REPLACE_VALS
  
    DBG("SBC: connecting to '%s'\n",ruri.c_str());
***************
*** 810,815 ****
--- 859,866 ----
        CALL_EVENT_H(onSipRequest,req);
    }
  
+   if (req.method == "CANCEL") decCallControlCalls();
+ 
    if (fwd && call_profile.messagefilter != Transparent) {
      bool is_filtered = (call_profile.messagefilter == Whitelist) ^ 
        (call_profile.messagefilter_list.find(req.method) != 
***************
*** 859,864 ****
--- 910,916 ----
      }
      else {
        DBG("Callee final error with code %d\n",reply.code);
+       decCallControlCalls();
        ret = AmB2BCallerSession::onOtherReply(reply);
      }
    }
***************
*** 869,874 ****
--- 921,927 ----
  void SBCDialog::onOtherBye(const AmSipRequest& req)
  {
    stopPrepaidAccounting();
+   decCallControlCalls();
    stopCallTimer();
    AmB2BCallerSession::onOtherBye(req);
  }
***************
*** 891,896 ****
--- 944,950 ----
  void SBCDialog::stopCall() {
    if (m_state == BB_Connected) {
      stopPrepaidAccounting();
+     decCallControlCalls();
      stopCallTimer();
    }
    terminateOtherLeg();
***************
*** 987,992 ****
--- 1041,1068 ----
    }
  }
  
+ void SBCDialog::decCallControlCalls() {
+ 
+   if (!call_profile.call_control_enabled)
+     return;
+ 
+   call_control_calls_mut.lock();
+   std::map<string, unsigned short>::iterator it = 
+       call_control_calls.find(call_profile.call_control_uuid);
+   if (it == call_control_calls.end()) {
+       call_control_calls_mut.unlock();
+       return;
+   }
+   if (it->second > 1) {
+       call_control_calls[call_profile.call_control_uuid]--;
+   } else {
+       call_control_calls.erase(it);
+   }
+   call_control_calls_mut.unlock();
+   call_control_calls_mut.unlock();
+   return;
+ }
+ 
  void SBCDialog::createCalleeSession()
  {
    SBCCalleeSession* callee_session = new SBCCalleeSession(this, call_profile);
diff -c -r /usr/src/orig/sems/apps/sbc//SBC.h ./SBC.h
*** /usr/src/orig/sems/apps/sbc//SBC.h  2011-09-17 14:08:27.000000000 +0300
--- ./SBC.h     2011-09-17 10:32:24.000000000 +0300
***************
*** 122,127 ****
--- 122,130 ----
    void startPrepaidAccounting();
    void stopPrepaidAccounting();
  
+   // call control
+   void decCallControlCalls();
+ 
    bool getPrepaidInterface();
  
   public:
_______________________________________________
Semsdev mailing list
[email protected]
http://lists.iptel.org/mailman/listinfo/semsdev

Reply via email to