Browse code

Merge remote-tracking branch 'origin/master' into 1.6-dev

* origin/master: (35 commits)
sbc:dsm: support for noAudio event
OA q/f: clear OA state upon sending final non-ok reply
b/f: initialize AmRtpStream::force_receive_dtmf
b/f:sbc:apply rtprelay_dtmf_filtering and rtprelay_dtmf_detection also on B leg
core: add Referred-By to AmSipDialog::refer()
dsm:mod_utils: added utils.escapeCRLF($var) and utils.unescapeCRLF($var)
sbc:dsm: rtp_interface for addCallee
c/f: fix outbound interface evaluation
c/f: fix outbound interface sbc sm option
sbc:dsm: outbound_interface for addCallee new call mode
sbc:dsm: next_hop options for addCallee with new call mode
b/f:b2b: remember 'receiving' in AudioStreamData, to restore after re-init
sbc: b/f: correct fix for nat_handling flag support
b/f:doc:dsm sbc typo
core: only use setter for AmRtpStream::receiving
b/f:rtp stream: if not receiving, still handle symmetricRtp
dsm: add more clear debugging on transitions
core: make sure that session is started when 200 ok is received after 183
sbc b/f: handle reINVITE within disconnected B2B call better way
sbc: core_options_handling=yes will make standard OPTIONS processing in the core
...

Stefan Sayer authored on 20/01/2014 16:24:16
Showing 15 changed files
... ...
@@ -67,6 +67,7 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) {
67 67
   DEF_CMD("getRecordLength", SCGetRecordLengthAction);
68 68
   DEF_CMD("getRecordDataSize", SCGetRecordDataSizeAction);
69 69
   DEF_CMD("flushPlaylist", SCFlushPlaylistAction);
70
+  DEF_CMD("closePlaylist", SCClosePlaylistAction); // deprecated
70 71
   DEF_CMD("setInOutPlaylist", SCSetInOutPlaylistAction);
71 72
   DEF_CMD("setInputPlaylist", SCSetInputPlaylistAction);
72 73
   DEF_CMD("setOutputPlaylist", SCSetOutputPlaylistAction);
... ...
@@ -398,6 +399,11 @@ EXEC_ACTION_START(SCFlushPlaylistAction) {
398 399
   sc_sess->flushPlaylist();
399 400
 } EXEC_ACTION_END;
400 401
 
402
+EXEC_ACTION_START(SCClosePlaylistAction) {
403
+  WARN("closePlaylist() is deprecated - please use flushPlaylist() instead\n");
404
+  sc_sess->flushPlaylist();
405
+} EXEC_ACTION_END;
406
+
401 407
 
402 408
 EXEC_ACTION_START(SCSetInOutPlaylistAction) {
403 409
   sc_sess->setInOutPlaylist();
... ...
@@ -55,6 +55,7 @@ DEF_ACTION_1P(SCStopRecordAction);
55 55
 DEF_ACTION_1P(SCGetRecordDataSizeAction);
56 56
 DEF_ACTION_1P(SCGetRecordLengthAction);
57 57
 DEF_ACTION_1P(SCFlushPlaylistAction);
58
+DEF_ACTION_1P(SCClosePlaylistAction);
58 59
 DEF_ACTION_1P(SCSetInOutPlaylistAction);
59 60
 DEF_ACTION_1P(SCSetInputPlaylistAction);
60 61
 DEF_ACTION_1P(SCSetOutputPlaylistAction);
... ...
@@ -149,6 +149,7 @@ SimpleRelayCreator::createGenericRelay(SBCCallProfile& call_profile,
149 149
 SBCFactory::SBCFactory(const string& _app_name)
150 150
   : AmSessionFactory(_app_name), 
151 151
     AmDynInvokeFactory(_app_name),
152
+    core_options_handling(false),
152 153
     callLegCreator(new CallLegCreator()),
153 154
     simpleRelayCreator(new SimpleRelayCreator())
154 155
 {
... ...
@@ -230,6 +231,9 @@ int SBCFactory::onLoad()
230 231
     INFO("loaded regex mapping '%s'\n", it->c_str());
231 232
   }
232 233
 
234
+  core_options_handling = cfg.getParameter("core_options_handling") == "yes";
235
+  DBG("OPTIONS messages handled by the core: %s\n", core_options_handling?"yes":"no");
236
+
233 237
   if (!AmPlugIn::registerApplication(MOD_NAME, this)) {
234 238
     ERROR("registering "MOD_NAME" application\n");
235 239
     return -1;
... ...
@@ -353,6 +357,13 @@ void oodHandlingTerminated(const AmSipRequest &req, vector<AmDynInvoke*>& cc_mod
353 357
 void SBCFactory::onOoDRequest(const AmSipRequest& req)
354 358
 {
355 359
   DBG("processing message %s %s\n", req.method.c_str(), req.r_uri.c_str());  
360
+
361
+  if (core_options_handling && req.method == SIP_METH_OPTIONS) {
362
+    DBG("processing OPTIONS in core\n");
363
+    AmSessionFactory::onOoDRequest(req);
364
+    return;
365
+  }
366
+
356 367
   profiles_mut.lock();
357 368
 
358 369
   ParamReplacerCtx ctx;
... ...
@@ -72,6 +72,8 @@ class SBCFactory: public AmSessionFactory,
72 72
   vector<string> active_profile;
73 73
   AmMutex profiles_mut;
74 74
 
75
+  bool core_options_handling;
76
+
75 77
   auto_ptr<CallLegCreator> callLegCreator;
76 78
   auto_ptr<SimpleRelayCreator> simpleRelayCreator;
77 79
 
... ...
@@ -31,6 +31,10 @@ active_profile=transparent
31 31
 # e.g. load_cc_plugins=cc_pcalls;cc_ctl
32 32
 #load_cc_plugins=cc_pcalls;cc_ctl
33 33
 
34
+# handle OPTIONS messages in the core? (with limits etc)
35
+# Default: no
36
+#core_options_handling=yes
37
+
34 38
 ## RFC4028 Session Timer
35 39
 # default configuration - can be overridden by call profiles
36 40
 
... ...
@@ -573,7 +573,6 @@ int AmBasicSipDialog::reply(const AmSipRequest& req,
573 573
   }
574 574
   DBG("reply: transaction found!\n");
575 575
     
576
-  string m_hdrs = hdrs;
577 576
   AmSipReply reply;
578 577
 
579 578
   reply.code = code;
... ...
@@ -581,7 +580,7 @@ int AmBasicSipDialog::reply(const AmSipRequest& req,
581 580
   reply.tt = req.tt;
582 581
   if((code > 100) && !(flags & SIP_FLAGS_NOTAG))
583 582
     reply.to_tag = ext_local_tag.empty() ? local_tag : ext_local_tag;
584
-  reply.hdrs = m_hdrs;
583
+  reply.hdrs = hdrs;
585 584
   reply.cseq = req.cseq;
586 585
   reply.cseq_method = req.method;
587 586
 
... ...
@@ -178,6 +178,10 @@ int AmOfferAnswer::onReplyIn(const AmSipReply& reply)
178 178
 	
179 179
 	DBG("ignoring subsequent SDP reply within the same transaction\n");
180 180
 	DBG("this usually happens when 183 and 200 have SDP\n");
181
+
182
+	/* Make sure that session is started when 200 OK is received */
183
+	if (reply.code == 200) dlg->onSdpCompleted();
184
+
181 185
       }
182 186
       else {
183 187
 	saveState();
... ...
@@ -409,6 +413,14 @@ int AmOfferAnswer::onReplyOut(AmSipReply& reply)
409 413
     return -1;
410 414
   }
411 415
 
416
+  if( (reply.code >= 300) &&
417
+      (reply.cseq == cseq) ) {
418
+    // final error reply -> cleanup OA state
419
+    DBG("after %u reply to %s: resetting OA state\n",
420
+	reply.code, reply.cseq_method.c_str());
421
+    clearTransitionalState();
422
+  }
423
+
412 424
   return 0;
413 425
 }
414 426
 
... ...
@@ -406,7 +406,8 @@ void AmSessionContainer::setCPSSoftLimit(unsigned int percent)
406 406
       break;
407 407
     }
408 408
   }
409
-  CPSLimit = (percent / 100) * ((float)cps_queue.size() / CPS_SAMPLERATE);
409
+  CPSLimit = ((float)percent / 100) * ((float)cps_queue.size() / CPS_SAMPLERATE);
410
+  if(0 == CPSLimit) CPSLimit = 1;
410 411
 }
411 412
 
412 413
 pair<unsigned int, unsigned int> AmSessionContainer::getCPSLimit()
... ...
@@ -31,18 +31,15 @@
31 31
 #include "msg_fline.h"
32 32
 
33 33
 #include <assert.h>
34
+#include <stdlib.h>
34 35
 
35 36
 inline void status_code_wr(char** c, int code)
36 37
 {
37
-    int div = code / 100;
38
-    *((*c)++) = div + '0';
39
-    code -= div*100;
40
-
41
-    div = code / 10;
42
-    *((*c)++) = div + '0';
43
-    code -= div*10;
44
-    
45
-    *((*c)++) = code + '0';
38
+    div_t d = div(code, 100);
39
+    *((*c)++) = d.quot + '0';
40
+    d = div(d.rem, 10);
41
+    *((*c)++) = d.quot + '0';
42
+    *((*c)++) = d.rem + '0';
46 43
 }
47 44
 
48 45
 
... ...
@@ -142,8 +142,7 @@ Playing prompts and file I/O
142 142
  stopRecord()
143 143
  getRecordLength([dst_varname])   -- only while recording! default dst var: record_length
144 144
  getRecordDataSize([dst_varname]) -- only while recording! default dst var: record_data_size
145
- closePlaylist(notify=true)
146
-   if notify=true, send an event
145
+ flushPlaylist()
147 146
  setInOutPlaylist() 
148 147
    set playlist as input and output
149 148
  setInputPlaylist() 
... ...
@@ -4,7 +4,7 @@ Actions:
4 4
    Throws "conference" Exception if conference can not be joined (currently never).
5 5
 
6 6
  conference.leave()
7
-   destroy conference channel. Close playlist first!!!!!
7
+   destroy conference channel. Flush playlist with flushPlaylist() first!!!!!
8 8
    * Sets $errno (script).
9 9
 
10 10
  conference.rejoin(string roomname [, string mode])
... ...
@@ -115,7 +115,7 @@ FUNCTIONS
115 115
     addSeparator(string name[, bool front])
116 116
         add a named separator to playlist
117 117
 
118
-    closePlaylist(bool notify)
118
+    flushPlaylist()
119 119
         close the playlist
120 120
 
121 121
     connectMedia()
... ...
@@ -18,10 +18,10 @@ state ENTER_PIN;
18 18
 transition "got cancel from A leg" (START, RUN_INVITE, ENTER_PIN) - event(#a_status==CANCEL) / stop(true) -> END;
19 19
 
20 20
 transition "pressed a number" ENTER_PIN - key(#key<10) / {
21
-  closePlaylist(false); 
21
+  flushPlaylist(); 
22 22
   append($entered_pin, #key);
23 23
 } -> TEST_PIN;
24
-transition "pressed hash or start" ENTER_PIN - key / closePlaylist(false) -> TEST_PIN_FINAL;
24
+transition "pressed hash or start" ENTER_PIN - key / flushPlaylist() -> TEST_PIN_FINAL;
25 25
 
26 26
 state TEST_PIN
27 27
  enter {
... ...
@@ -133,7 +133,7 @@ transition "one more to cancel" CANCEL_OTHER_CALLEES - test($callee_counter<$db.
133 133
 } -> CANCEL_OTHER_CALLEES;
134 134
 
135 135
 transition "canceled all" CANCEL_OTHER_CALLEES - test($callee_counter==$db.rows) / {
136
-  closePlaylist(false);
136
+  flushPlaylist();
137 137
   dlg.acceptInvite(200, OK);
138 138
   conference.join(@local_tag);
139 139
 } -> CONNECTED;
... ...
@@ -502,14 +502,14 @@ transition "pin doesn't match" TEST_PIN_FINAL - test($pin!=$entered_pin) / {
502 502
 state MATCHING_PIN;
503 503
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
504 504
 
505
-That works, but we want to break the prompt when the user enters a key, so we add closePlaylist(false), which stops playback of currently playing items in the playlist, but doesn't generate an event:
505
+That works, but we want to break the prompt when the user enters a key, so we add flushPlaylist(), which stops playback of currently playing items in the playlist (and doesn't generate an event):
506 506
 
507 507
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
508 508
 transition "pressed a number" ENTER_PIN - key(#key<10) / {
509
-  closePlaylist(false);
509
+  flushPlaylist();
510 510
   append($entered_pin, #key);
511 511
 } -> TEST_PIN;
512
-transition "pressed hash or start" ENTER_PIN - key / closePlaylist(false) -> TEST_PIN_FINAL;
512
+transition "pressed hash or start" ENTER_PIN - key / flushPlaylist() -> TEST_PIN_FINAL;
513 513
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
514 514
 
515 515
 Now I realize we need to pass the id of the caller leg to the callee leg as well, so we can post back events:
... ...
@@ -564,7 +564,7 @@ transition "one more to cancel" CANCEL_OTHER_CALLEES - test($callee_counter<$db.
564 564
 } -> CANCEL_OTHER_CALLEES;
565 565
 
566 566
 transition "canceled all" CANCEL_OTHER_CALLEES - test($callee_counter==$db.rows) / {
567
-  closePlaylist(false);
567
+  flushPlaylist();
568 568
   dlg.acceptInvite(200, OK);
569 569
   conference.join(@local_tag);
570 570
 } -> CONNECTED;