Browse code

apps/dsm/mod_sbc: added message_filter and message_list profile variables

Juha Heinanen authored on 22/05/2014 05:23:56
Showing 1 changed files
... ...
@@ -210,6 +210,7 @@ CONST_ACTION_2P(MODSBCActionProfileSet, ',', false);
210 210
 EXEC_ACTION_START(MODSBCActionProfileSet) {
211 211
   string profile_param = resolveVars(par1, sess, sc_sess, event_params);
212 212
   string value = resolveVars(par2, sess, sc_sess, event_params);
213
+  FilterEntry mf;
213 214
 
214 215
   ACTION_GET_PROFILE;
215 216
 
... ...
@@ -268,7 +269,6 @@ EXEC_ACTION_START(MODSBCActionProfileSet) {
268 269
 
269 270
   SET_TO_CALL_PROFILE("aleg_next_hop", aleg_next_hop);
270 271
 
271
-  // TODO: message_filter
272 272
   // TODO: header_filter
273 273
   // TODO: sdp_filter
274 274
 
... ...
@@ -312,6 +312,22 @@ EXEC_ACTION_START(MODSBCActionProfileSet) {
312 312
     EXEC_ACTION_STOP;
313 313
   }
314 314
 
315
+  if (profile_param == "message_filter") {
316
+    mf.filter_type = String2FilterType(value.c_str());
317
+    DBG("message_filter set to '%s'\n", value.c_str());
318
+    EXEC_ACTION_STOP;
319
+  }
320
+
321
+  if (profile_param == "message_list") {
322
+    vector<string> elems = explode(value, ",");
323
+    for (vector<string>::iterator it=elems.begin(); it != elems.end(); it++)
324
+      mf.filter_list.insert(*it);
325
+    profile->messagefilter.push_back(mf);
326
+    mf.filter_type = Undefined;
327
+    DBG("message_list set to '%s'\n", value.c_str());
328
+    EXEC_ACTION_STOP;
329
+  }
330
+
315 331
   }
316 332
 
317 333
   // TODO: Transcoder Settings
Browse code

c/f: fix of 3c06c6b23 for dsm/sbc call control module

Stefan Sayer authored on 28/04/2014 13:38:33
Showing 1 changed files
... ...
@@ -279,7 +279,7 @@ EXEC_ACTION_START(MODSBCActionProfileSet) {
279 279
   SET_TO_CALL_PROFILE("append_headers_req", append_headers_req);
280 280
   SET_TO_CALL_PROFILE("aleg_append_headers_req", aleg_append_headers_req);
281 281
 
282
-  SET_TO_CALL_PROFILE_OPTION("rtprelay_enabled", rtprelay_enabled);
282
+  SET_TO_CALL_PROFILE("rtprelay_enabled", rtprelay_enabled);
283 283
 
284 284
   SET_TO_CALL_PROFILE_OPTION("force_symmetric_rtp", force_symmetric_rtp_value);
285 285
   SET_TO_CALL_PROFILE_OPTION("aleg_force_symmetric_rtp", aleg_force_symmetric_rtp_value);
Browse code

sbc:dsm: conditions for call leg status

Stefan Sayer authored on 11/03/2014 14:38:57
Showing 1 changed files
... ...
@@ -117,6 +117,22 @@ MOD_CONDITIONEXPORT_BEGIN(MOD_CLS_NAME) {
117 117
   if (cmd == "sbc.isOnHold")
118 118
     return new SBCIsOnHoldCondition(params, false);
119 119
 
120
+  if (cmd == "sbc.isDisconnected")
121
+    return new SBCIsDisconnectedCondition(params, false);
122
+
123
+  if (cmd == "sbc.isNoReply")
124
+    return new SBCIsNoReplyCondition(params, false);
125
+
126
+  if (cmd == "sbc.isRinging")
127
+    return new SBCIsRingingCondition(params, false);
128
+
129
+  if (cmd == "sbc.isConnected")
130
+    return new SBCIsConnectedCondition(params, false);
131
+
132
+  if (cmd == "sbc.isDisconnecting")
133
+    return new SBCIsDisconnectingCondition(params, false);
134
+
135
+
120 136
 } MOD_CONDITIONEXPORT_END
121 137
 
122 138
 
... ...
@@ -150,6 +166,28 @@ MATCH_CONDITION_START(SBCIsOnHoldCondition) {
150 166
   return res;
151 167
 } MATCH_CONDITION_END;
152 168
 
169
+#define DEF_CALLSTATUS_COND(cond_name, cond_desc, call_status)		\
170
+									\
171
+  MATCH_CONDITION_START(cond_name) {					\
172
+    SBCCallLeg* call_leg = dynamic_cast<SBCCallLeg*>(sess);		\
173
+    if (NULL == call_leg) {						\
174
+      DBG("script writer error: DSM condition used without call leg\n"); \
175
+      return false;							\
176
+    }									\
177
+									\
178
+    bool b = call_leg->getCallStatus() == call_status;			\
179
+    bool res = inv ^ b;							\
180
+    DBG("SBC: " cond_desc " == %s (res = %s)\n",			\
181
+	b ? "true":"false", res ? "true":"false");			\
182
+    return res;								\
183
+  } MATCH_CONDITION_END
184
+
185
+
186
+DEF_CALLSTATUS_COND(SBCIsDisconnectedCondition, "sbc.isDisconnected", CallLeg::Disconnected);
187
+DEF_CALLSTATUS_COND(SBCIsNoReplyCondition, "sbc.isNoReply", CallLeg::NoReply);
188
+DEF_CALLSTATUS_COND(SBCIsRingingCondition, "sbc.isRinging", CallLeg::Ringing);
189
+DEF_CALLSTATUS_COND(SBCIsConnectedCondition, "sbc.isConnected", CallLeg::Connected);
190
+DEF_CALLSTATUS_COND(SBCIsDisconnectingCondition, "sbc.isDisconnecting", CallLeg::Disconnecting);
153 191
 
154 192
 #define ACTION_GET_PROFILE			\
155 193
   SBCCallProfile* profile = NULL;					\
Browse code

sbc:dsm: rtp_interface for addCallee

Stefan Sayer authored on 22/12/2013 00:07:42
Showing 1 changed files
... ...
@@ -474,6 +474,12 @@ EXEC_ACTION_START(MODSBCActionAddCallee) {
474 474
       p.evaluateOutboundInterface();
475 475
     }
476 476
 
477
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_RTP_INTERFACE);
478
+    if (it != sc_sess->var.end()) {
479
+      p.rtprelay_interface = it->second;
480
+      p.evaluateRTPRelayInterface();
481
+    }
482
+
477 483
     sbc_call_leg->addCallee(peer, hdrs);
478 484
   } else if (mode == DSM_SBC_PARAM_ADDCALLEE_MODE_LTAG) {
479 485
     string ltag;
Browse code

sbc:dsm: outbound_interface for addCallee new call mode

Stefan Sayer authored on 21/12/2013 19:41:06
Showing 1 changed files
... ...
@@ -468,6 +468,12 @@ EXEC_ACTION_START(MODSBCActionAddCallee) {
468 468
     if (it != sc_sess->var.end())
469 469
       p.next_hop_fixed = (it->second == DSM_TRUE);
470 470
 
471
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_OUTBOUND_INTERFACE);
472
+    if (it != sc_sess->var.end()) {
473
+      p.outbound_interface = it->second;
474
+      p.evaluateOutboundInterface();
475
+    }
476
+
471 477
     sbc_call_leg->addCallee(peer, hdrs);
472 478
   } else if (mode == DSM_SBC_PARAM_ADDCALLEE_MODE_LTAG) {
473 479
     string ltag;
Browse code

sbc:dsm: next_hop options for addCallee with new call mode

Stefan Sayer authored on 21/12/2013 18:23:38
Showing 1 changed files
... ...
@@ -452,6 +452,22 @@ EXEC_ACTION_START(MODSBCActionAddCallee) {
452 452
     if (it != sc_sess->var.end())
453 453
       p.outbound_proxy = it->second;
454 454
 
455
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_NEXT_HOP);
456
+    if (it != sc_sess->var.end())
457
+      p.next_hop = it->second;
458
+
459
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_NEXT_HOP_1ST_REQ);
460
+    if (it != sc_sess->var.end())
461
+      p.next_hop_1st_req = (it->second == DSM_TRUE);
462
+
463
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_NEXT_HOP_PATCH_RURI);
464
+    if (it != sc_sess->var.end())
465
+      p.patch_ruri_next_hop = (it->second == DSM_TRUE);
466
+
467
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_NEXT_HOP_FIXED);
468
+    if (it != sc_sess->var.end())
469
+      p.next_hop_fixed = (it->second == DSM_TRUE);
470
+
455 471
     sbc_call_leg->addCallee(peer, hdrs);
456 472
   } else if (mode == DSM_SBC_PARAM_ADDCALLEE_MODE_LTAG) {
457 473
     string ltag;
Browse code

b/f:b2b: remember 'receiving' in AudioStreamData, to restore after re-init

also removed dsm sbc mute/unmute functions, as they need to use other proper functions

Stefan Sayer authored on 17/12/2013 13:18:37
Showing 1 changed files
... ...
@@ -59,11 +59,7 @@ MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
59 59
   DEF_CMD("sbc.addToMediaProcessor", MODSBCAddToMediaProcessor);
60 60
   DEF_CMD("sbc.removeFromMediaProcessor", MODSBCRemoveFromMediaProcessor);
61 61
 
62
-  DEF_CMD("sbc.pauseRtpStreams", MODSBCPauseRtpStreams);
63
-  DEF_CMD("sbc.resumeRtpStreams", MODSBCResumeRtpStreams);
64
-
65
-  DEF_CMD("sbc.muteRtpStreams", MODSBCMuteRtpStreams);
66
-  DEF_CMD("sbc.unmuteRtpStreams", MODSBCUnmuteRtpStreams);
62
+  DEF_CMD("sbc.streamsSetReceiving", MODSBCRtpStreamsSetReceiving);
67 63
 
68 64
 } MOD_ACTIONEXPORT_END;
69 65
 
... ...
@@ -494,46 +490,13 @@ EXEC_ACTION_START(MODSBCRemoveFromMediaProcessor) {
494 490
   AmMediaProcessor::instance()->removeSession(call_leg);
495 491
 } EXEC_ACTION_END;
496 492
 
497
-CONST_ACTION_2P(MODSBCPauseRtpStreams, ',', false);
498
-EXEC_ACTION_START(MODSBCPauseRtpStreams) {
499
-  bool p_a = (resolveVars(par1, sess, sc_sess, event_params)==DSM_TRUE);
500
-  bool p_b = (resolveVars(par2, sess, sc_sess, event_params)==DSM_TRUE);
501
-
502
-  GET_SBC_CALL_LEG(PauseRtpStream);
503
-  GET_B2B_MEDIA;
504
-
505
-  b2b_media->pauseStreams(p_a, p_b);
506
-} EXEC_ACTION_END;
507
-
508
-CONST_ACTION_2P(MODSBCResumeRtpStreams, ',', false);
509
-EXEC_ACTION_START(MODSBCResumeRtpStreams) {
510
-  bool p_a = (resolveVars(par1, sess, sc_sess, event_params)==DSM_TRUE);
511
-  bool p_b = (resolveVars(par2, sess, sc_sess, event_params)==DSM_TRUE);
512
-
513
-  GET_SBC_CALL_LEG(ResumeRtpStream);
514
-
515
-  GET_B2B_MEDIA;
516
-  b2b_media->resumeStreams(p_a, p_b);
517
-} EXEC_ACTION_END;
518
-
519
-CONST_ACTION_2P(MODSBCMuteRtpStreams, ',', false);
520
-EXEC_ACTION_START(MODSBCMuteRtpStreams) {
521
-  bool p_a = (resolveVars(par1, sess, sc_sess, event_params)==DSM_TRUE);
522
-  bool p_b = (resolveVars(par2, sess, sc_sess, event_params)==DSM_TRUE);
523
-
524
-  GET_SBC_CALL_LEG(muteRtpStreams);
525
-  GET_B2B_MEDIA;
526
-
527
-  b2b_media->muteStreams(p_a, p_b);
528
-} EXEC_ACTION_END;
529
-
530
-CONST_ACTION_2P(MODSBCUnmuteRtpStreams, ',', false);
531
-EXEC_ACTION_START(MODSBCUnmuteRtpStreams) {
493
+CONST_ACTION_2P(MODSBCRtpStreamsSetReceiving, ',', false);
494
+EXEC_ACTION_START(MODSBCRtpStreamsSetReceiving) {
532 495
   bool p_a = (resolveVars(par1, sess, sc_sess, event_params)==DSM_TRUE);
533 496
   bool p_b = (resolveVars(par2, sess, sc_sess, event_params)==DSM_TRUE);
534 497
 
535
-  GET_SBC_CALL_LEG(unmuteRtpStreams);
498
+  GET_SBC_CALL_LEG(RtpStreamsSetReceiving);
536 499
   GET_B2B_MEDIA;
537 500
 
538
-  b2b_media->unmuteStreams(p_a, p_b);
501
+  b2b_media->setReceiving(p_a, p_b);
539 502
 } EXEC_ACTION_END;
Browse code

b/f:sbc:dsm: sbc.addCallee for new call with non-transparent dlg id

Stefan Sayer authored on 21/11/2013 15:28:49
Showing 1 changed files
... ...
@@ -423,11 +423,24 @@ EXEC_ACTION_START(MODSBCActionAddCallee) {
423 423
 
424 424
   if (mode == DSM_SBC_PARAM_ADDCALLEE_MODE_STR) {
425 425
     string hdrs;
426
+
427
+    VarMapT::iterator it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_TRANSPARENT_DLG_ID);
428
+    if (it != sc_sess->var.end()) {
429
+      sbc_call_leg->getCallProfile().transparent_dlg_id = it->second == DSM_TRUE;
430
+    } else {
431
+      // default to false
432
+      sbc_call_leg->getCallProfile().transparent_dlg_id = false;
433
+    }
434
+
435
+      DBG("Using %stransparent dialog IDs for new call leg\n",
436
+	  sbc_call_leg->getCallProfile().transparent_dlg_id ? "":"non-");
437
+
426 438
     SBCCallLeg* peer = new SBCCallLeg(sbc_call_leg);
439
+
427 440
     SBCCallProfile &p = peer->getCallProfile();
428 441
     AmB2BSession::RTPRelayMode rtp_mode = sbc_call_leg->getRtpRelayMode();
429 442
 
430
-    VarMapT::iterator it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_LOCAL_PARTY);
443
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_LOCAL_PARTY);
431 444
     if (it != sc_sess->var.end())
432 445
       peer->setLocalParty(it->second, it->second);
433 446
 
Browse code

Merge remote-tracking branch 'frafos/1.6-dev' into 1.6-dev-ccdsm

* frafos/1.6-dev: (27 commits)
b2b calls quick hack: make RelayController accessible from derrived classes
sbc: keep original CSeq to support authentication case with Asterisk
sbc: allow to preserve media session when disconnecting
core: disable blacklist for in-dialog requests
sip: disable blacklist lookup if TR_FLAG_DISABLE_BL flag is set
sip: do not insert into blacklist if duration == 0
sbc: added active registration counter
b2b media b/f: do not try to set relay with empty remote address
AmRtpStream b/f: do not set mute together with hold
core: CPS limiter Calls-per-sec limiting capability, similar to the maximum number of calls limiter. There is a "soft limit" that is intended to use by the applications: if the app uses async processing and detects that the incoming workload is too much for the currenti capacity (which can depend on for example the remote DB engine's load), it can slewi it back to some percent of the current CPS; then when the circumstances are restored it can switch the CPS limit back to the configuration (or XMLRPC/stats interface) mandated value.
sbc: use non-hold SDP if possible when adding new callee
sbc: new event for asynchronous held call resume
b2b media cleanup: remove unused methods
sbc b/f: create hold request cleaner way
sbc b/f: signalize hold/resume request before creating the hold/resume request itself
webconference: add lonely_user_timer option
sbc b/f: apply remote SDP again if RTP mode changed during OA exchange
b2b media b/f: do not clear audio when removed from media processor
core: b/f: make get_header_keyvalue_single() case-insensitive as specified in RFC3261 7.3.1
sbc: improved hold handling
...

Conflicts:
apps/sbc/CallLeg.cpp
core/AmB2BMedia.h

Stefan Sayer authored on 13/11/2013 16:02:45
Showing 0 changed files
Browse code

sbc:dsm: addCallee mode ltag - reconnect existing callee leg

Stefan Sayer authored on 11/11/2013 18:51:50
Showing 1 changed files
... ...
@@ -418,9 +418,9 @@ EXEC_ACTION_START(MODSBCActionAddCallee) {
418 418
   GET_SBC_CALL_LEG(sbc.addCallee);
419 419
 
420 420
   string mode = resolveVars(par1, sess, sc_sess, event_params);
421
+  string varname = par2;
421 422
 
422 423
   if (mode == DSM_SBC_PARAM_ADDCALLEE_MODE_STR) {
423
-    string varname = par2;
424 424
     string hdrs;
425 425
     SBCCallLeg* peer = new SBCCallLeg(sbc_call_leg);
426 426
     SBCCallProfile &p = peer->getCallProfile();
... ...
@@ -456,6 +456,19 @@ EXEC_ACTION_START(MODSBCActionAddCallee) {
456 456
     }
457 457
 
458 458
     sbc_call_leg->addCallee(peer, hdrs, rtp_mode);
459
+  } else if (mode == DSM_SBC_PARAM_ADDCALLEE_MODE_LTAG) {
460
+    string ltag;
461
+    string hdrs;
462
+
463
+    VarMapT::iterator it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_LTAG);
464
+    if (it != sc_sess->var.end())
465
+      ltag = it->second;
466
+
467
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_HDRS);
468
+    if (it != sc_sess->var.end())
469
+      hdrs = it->second;
470
+
471
+    sbc_call_leg->addCallee(ltag, hdrs);
459 472
   }
460 473
 
461 474
 } EXEC_ACTION_END;
Browse code

sbc:dsm: pause/resume/mute/unmute rtp streams functions

Stefan Sayer authored on 10/11/2013 17:24:23
Showing 1 changed files
... ...
@@ -58,6 +58,13 @@ MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
58 58
   DEF_CMD("sbc.enableRelayDTMFReceiving", MODSBCEnableRelayDTMFReceiving);
59 59
   DEF_CMD("sbc.addToMediaProcessor", MODSBCAddToMediaProcessor);
60 60
   DEF_CMD("sbc.removeFromMediaProcessor", MODSBCRemoveFromMediaProcessor);
61
+
62
+  DEF_CMD("sbc.pauseRtpStreams", MODSBCPauseRtpStreams);
63
+  DEF_CMD("sbc.resumeRtpStreams", MODSBCResumeRtpStreams);
64
+
65
+  DEF_CMD("sbc.muteRtpStreams", MODSBCMuteRtpStreams);
66
+  DEF_CMD("sbc.unmuteRtpStreams", MODSBCUnmuteRtpStreams);
67
+
61 68
 } MOD_ACTIONEXPORT_END;
62 69
 
63 70
 MOD_CONDITIONEXPORT_BEGIN(MOD_CLS_NAME) {
... ...
@@ -295,6 +302,26 @@ EXEC_ACTION_START(MODSBCActionProfileSet) {
295 302
 		       " used without call leg");			\
296 303
   }
297 304
 
305
+#define GET_SBC_CALL_LEG(action)					\
306
+  SBCCallLeg* sbc_call_leg = dynamic_cast<SBCCallLeg*>(sess);		\
307
+  if (NULL == sbc_call_leg) {						\
308
+    DBG("script writer error: DSM action " #action			\
309
+	" used without sbc call leg\n");				\
310
+    throw DSMException("sbc", "type", "param", "cause",			\
311
+		       "script writer error: DSM action " #action	\
312
+		       " used without sbc call leg");			\
313
+  }
314
+
315
+#define GET_B2B_MEDIA							\
316
+  AmB2BMedia* b2b_media = sbc_call_leg->getMediaSession();		\
317
+  DBG("session: %p, media: %p\n", sbc_call_leg, b2b_media);		\
318
+  if (NULL == b2b_media) {						\
319
+    DBG("No B2BMedia in current SBC call leg, sorry\n");		\
320
+    sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);				\
321
+    sc_sess->SET_STRERROR("No B2BMedia in current SBC call leg, sorry"); \
322
+    EXEC_ACTION_STOP;							\
323
+  }
324
+
298 325
 EXEC_ACTION_START(MODSBCActionStopCall) {
299 326
   GET_CALL_LEG(StopCall);
300 327
   string cause = resolveVars(arg, sess, sc_sess, event_params);
... ...
@@ -388,17 +415,7 @@ EXEC_ACTION_START(MODSBCActionB2BRelayReliable) {
388 415
 
389 416
 CONST_ACTION_2P(MODSBCActionAddCallee, ',', false);
390 417
 EXEC_ACTION_START(MODSBCActionAddCallee) {
391
-  GET_CALL_LEG(AddCallee);
392
-
393
-  SBCCallLeg* sbc_call_leg = dynamic_cast<SBCCallLeg*>(call_leg);
394
-  if (NULL == sbc_call_leg) {
395
-    DBG("script writer error: DSM action sbc.addCallee "
396
-	" used without sbc call leg\n");
397
-    throw DSMException("sbc", "type", "param", "cause",
398
-		       "script writer error: DSM action sbc.addCallee "
399
-		       " used without call leg");
400
-    EXEC_ACTION_STOP;
401
-  }
418
+  GET_SBC_CALL_LEG(sbc.addCallee);
402 419
 
403 420
   string mode = resolveVars(par1, sess, sc_sess, event_params);
404 421
 
... ...
@@ -407,7 +424,7 @@ EXEC_ACTION_START(MODSBCActionAddCallee) {
407 424
     string hdrs;
408 425
     SBCCallLeg* peer = new SBCCallLeg(sbc_call_leg);
409 426
     SBCCallProfile &p = peer->getCallProfile();
410
-    AmB2BSession::RTPRelayMode rtp_mode = call_leg->getRtpRelayMode();
427
+    AmB2BSession::RTPRelayMode rtp_mode = sbc_call_leg->getRtpRelayMode();
411 428
 
412 429
     VarMapT::iterator it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_LOCAL_PARTY);
413 430
     if (it != sc_sess->var.end())
... ...
@@ -444,27 +461,12 @@ EXEC_ACTION_START(MODSBCActionAddCallee) {
444 461
 } EXEC_ACTION_END;
445 462
 
446 463
 EXEC_ACTION_START(MODSBCEnableRelayDTMFReceiving) {
447
-  GET_CALL_LEG(AddCallee);
448
-
449 464
   bool enable = (resolveVars(arg, sess, sc_sess, event_params)==DSM_TRUE);
450 465
 
451
-  SBCCallLeg* sbc_call_leg = dynamic_cast<SBCCallLeg*>(call_leg);
452
-  if (NULL == sbc_call_leg) {
453
-    DBG("script writer error: DSM action sbc.addCallee "
454
-	" used without sbc call leg\n");
455
-    throw DSMException("sbc", "type", "param", "cause",
456
-		       "script writer error: DSM action sbc.addCallee "
457
-		       " used without call leg");
458
-    EXEC_ACTION_STOP;
459
-  }
466
+  GET_SBC_CALL_LEG(AddCallee);
467
+  GET_B2B_MEDIA;
460 468
 
461
-  AmB2BMedia* b2b_media = sbc_call_leg->getMediaSession();
462
-  DBG("session: %p, media: %p\n", sbc_call_leg, b2b_media);
463
-  if (NULL != b2b_media) {
464
-    b2b_media->setRelayDTMFReceiving(enable);
465
-  } else {
466
-    DBG("No B2BMedia in current SBC call leg, sorry\n");
467
-  }
469
+  b2b_media->setRelayDTMFReceiving(enable);
468 470
 } EXEC_ACTION_END;
469 471
 
470 472
 EXEC_ACTION_START(MODSBCAddToMediaProcessor) {
... ...
@@ -477,4 +479,47 @@ EXEC_ACTION_START(MODSBCRemoveFromMediaProcessor) {
477 479
   GET_CALL_LEG(RemoveFromMediaProcessor);
478 480
   AmMediaProcessor::instance()->removeSession(call_leg);
479 481
 } EXEC_ACTION_END;
480
-  
482
+
483
+CONST_ACTION_2P(MODSBCPauseRtpStreams, ',', false);
484
+EXEC_ACTION_START(MODSBCPauseRtpStreams) {
485
+  bool p_a = (resolveVars(par1, sess, sc_sess, event_params)==DSM_TRUE);
486
+  bool p_b = (resolveVars(par2, sess, sc_sess, event_params)==DSM_TRUE);
487
+
488
+  GET_SBC_CALL_LEG(PauseRtpStream);
489
+  GET_B2B_MEDIA;
490
+
491
+  b2b_media->pauseStreams(p_a, p_b);
492
+} EXEC_ACTION_END;
493
+
494
+CONST_ACTION_2P(MODSBCResumeRtpStreams, ',', false);
495
+EXEC_ACTION_START(MODSBCResumeRtpStreams) {
496
+  bool p_a = (resolveVars(par1, sess, sc_sess, event_params)==DSM_TRUE);
497
+  bool p_b = (resolveVars(par2, sess, sc_sess, event_params)==DSM_TRUE);
498
+
499
+  GET_SBC_CALL_LEG(ResumeRtpStream);
500
+
501
+  GET_B2B_MEDIA;
502
+  b2b_media->resumeStreams(p_a, p_b);
503
+} EXEC_ACTION_END;
504
+
505
+CONST_ACTION_2P(MODSBCMuteRtpStreams, ',', false);
506
+EXEC_ACTION_START(MODSBCMuteRtpStreams) {
507
+  bool p_a = (resolveVars(par1, sess, sc_sess, event_params)==DSM_TRUE);
508
+  bool p_b = (resolveVars(par2, sess, sc_sess, event_params)==DSM_TRUE);
509
+
510
+  GET_SBC_CALL_LEG(muteRtpStreams);
511
+  GET_B2B_MEDIA;
512
+
513
+  b2b_media->muteStreams(p_a, p_b);
514
+} EXEC_ACTION_END;
515
+
516
+CONST_ACTION_2P(MODSBCUnmuteRtpStreams, ',', false);
517
+EXEC_ACTION_START(MODSBCUnmuteRtpStreams) {
518
+  bool p_a = (resolveVars(par1, sess, sc_sess, event_params)==DSM_TRUE);
519
+  bool p_b = (resolveVars(par2, sess, sc_sess, event_params)==DSM_TRUE);
520
+
521
+  GET_SBC_CALL_LEG(unmuteRtpStreams);
522
+  GET_B2B_MEDIA;
523
+
524
+  b2b_media->unmuteStreams(p_a, p_b);
525
+} EXEC_ACTION_END;
Browse code

sbc:dsm: DTMF related function (DTMF detection in relayed calls)

Stefan Sayer authored on 06/11/2013 00:06:01
Showing 1 changed files
... ...
@@ -55,6 +55,9 @@ MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
55 55
 
56 56
   DEF_CMD("sbc.addCallee", MODSBCActionAddCallee);
57 57
 
58
+  DEF_CMD("sbc.enableRelayDTMFReceiving", MODSBCEnableRelayDTMFReceiving);
59
+  DEF_CMD("sbc.addToMediaProcessor", MODSBCAddToMediaProcessor);
60
+  DEF_CMD("sbc.removeFromMediaProcessor", MODSBCRemoveFromMediaProcessor);
58 61
 } MOD_ACTIONEXPORT_END;
59 62
 
60 63
 MOD_CONDITIONEXPORT_BEGIN(MOD_CLS_NAME) {
... ...
@@ -243,6 +246,9 @@ EXEC_ACTION_START(MODSBCActionProfileSet) {
243 246
   SET_TO_CALL_PROFILE_OPTION("rtprelay_transparent_seqno", rtprelay_transparent_seqno);
244 247
   SET_TO_CALL_PROFILE_OPTION("rtprelay_transparent_ssrc", rtprelay_transparent_ssrc);
245 248
 
249
+  SET_TO_CALL_PROFILE_OPTION("rtprelay_dtmf_filtering", rtprelay_dtmf_filtering);
250
+  SET_TO_CALL_PROFILE_OPTION("rtprelay_dtmf_detection", rtprelay_dtmf_detection);
251
+
246 252
   if (profile_param == "rtprelay_interface") {
247 253
     profile->rtprelay_interface=value;
248 254
     if (!profile->evaluateRTPRelayInterface()) {
... ...
@@ -436,3 +442,39 @@ EXEC_ACTION_START(MODSBCActionAddCallee) {
436 442
   }
437 443
 
438 444
 } EXEC_ACTION_END;
445
+
446
+EXEC_ACTION_START(MODSBCEnableRelayDTMFReceiving) {
447
+  GET_CALL_LEG(AddCallee);
448
+
449
+  bool enable = (resolveVars(arg, sess, sc_sess, event_params)==DSM_TRUE);
450
+
451
+  SBCCallLeg* sbc_call_leg = dynamic_cast<SBCCallLeg*>(call_leg);
452
+  if (NULL == sbc_call_leg) {
453
+    DBG("script writer error: DSM action sbc.addCallee "
454
+	" used without sbc call leg\n");
455
+    throw DSMException("sbc", "type", "param", "cause",
456
+		       "script writer error: DSM action sbc.addCallee "
457
+		       " used without call leg");
458
+    EXEC_ACTION_STOP;
459
+  }
460
+
461
+  AmB2BMedia* b2b_media = sbc_call_leg->getMediaSession();
462
+  DBG("session: %p, media: %p\n", sbc_call_leg, b2b_media);
463
+  if (NULL != b2b_media) {
464
+    b2b_media->setRelayDTMFReceiving(enable);
465
+  } else {
466
+    DBG("No B2BMedia in current SBC call leg, sorry\n");
467
+  }
468
+} EXEC_ACTION_END;
469
+
470
+EXEC_ACTION_START(MODSBCAddToMediaProcessor) {
471
+  GET_CALL_LEG(AddToMediaProcessor);
472
+  AmMediaProcessor::instance()->addSession(call_leg, call_leg->getCallgroup());
473
+
474
+} EXEC_ACTION_END;
475
+
476
+EXEC_ACTION_START(MODSBCRemoveFromMediaProcessor) {
477
+  GET_CALL_LEG(RemoveFromMediaProcessor);
478
+  AmMediaProcessor::instance()->removeSession(call_leg);
479
+} EXEC_ACTION_END;
480
+  
Browse code

sbc:dsm: sendDisconnectEvent and addCallee actions

Stefan Sayer authored on 05/11/2013 11:44:34
Showing 1 changed files
... ...
@@ -48,10 +48,13 @@ MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
48 48
   DEF_CMD("sbc.disconnect", MODSBCActionDisconnect);
49 49
   DEF_CMD("sbc.putOnHold", MODSBCActionPutOnHold);
50 50
   DEF_CMD("sbc.resumeHeld", MODSBCActionResumeHeld);
51
+  DEF_CMD("sbc.sendDisconnectEvent", MODSBCActionSendDisconnectEvent);
51 52
 
52 53
   DEF_CMD("sbc.getCallStatus", MODSBCActionGetCallStatus);
53 54
   DEF_CMD("sbc.relayReliableEvent", MODSBCActionB2BRelayReliable);
54 55
 
56
+  DEF_CMD("sbc.addCallee", MODSBCActionAddCallee);
57
+
55 58
 } MOD_ACTIONEXPORT_END;
56 59
 
57 60
 MOD_CONDITIONEXPORT_BEGIN(MOD_CLS_NAME) {
... ...
@@ -298,6 +301,15 @@ EXEC_ACTION_START(MODSBCActionDisconnect) {
298 301
   call_leg->disconnect(hold_remote == DSM_TRUE);
299 302
 } EXEC_ACTION_END;
300 303
 
304
+EXEC_ACTION_START(MODSBCActionSendDisconnectEvent) {
305
+  GET_CALL_LEG(SendDisconnectEvent);
306
+  string hold_remote = resolveVars(arg, sess, sc_sess, event_params);
307
+  if (!AmSessionContainer::instance()->postEvent(call_leg->getLocalTag(),
308
+						 new DisconnectLegEvent(hold_remote == DSM_TRUE))) {
309
+    ERROR("couldn't self-post event\n");
310
+  }
311
+} EXEC_ACTION_END;
312
+
301 313
 
302 314
 EXEC_ACTION_START(MODSBCActionPutOnHold) {
303 315
   GET_CALL_LEG(PutOnHold);
... ...
@@ -367,3 +379,60 @@ EXEC_ACTION_START(MODSBCActionB2BRelayReliable) {
367 379
   rel_b2b_ev->setSender(call_leg->getLocalTag());
368 380
   call_leg->relayEvent(rel_b2b_ev);
369 381
 } EXEC_ACTION_END;
382
+
383
+CONST_ACTION_2P(MODSBCActionAddCallee, ',', false);
384
+EXEC_ACTION_START(MODSBCActionAddCallee) {
385
+  GET_CALL_LEG(AddCallee);
386
+
387
+  SBCCallLeg* sbc_call_leg = dynamic_cast<SBCCallLeg*>(call_leg);
388
+  if (NULL == sbc_call_leg) {
389
+    DBG("script writer error: DSM action sbc.addCallee "
390
+	" used without sbc call leg\n");
391
+    throw DSMException("sbc", "type", "param", "cause",
392
+		       "script writer error: DSM action sbc.addCallee "
393
+		       " used without call leg");
394
+    EXEC_ACTION_STOP;
395
+  }
396
+
397
+  string mode = resolveVars(par1, sess, sc_sess, event_params);
398
+
399
+  if (mode == DSM_SBC_PARAM_ADDCALLEE_MODE_STR) {
400
+    string varname = par2;
401
+    string hdrs;
402
+    SBCCallLeg* peer = new SBCCallLeg(sbc_call_leg);
403
+    SBCCallProfile &p = peer->getCallProfile();
404
+    AmB2BSession::RTPRelayMode rtp_mode = call_leg->getRtpRelayMode();
405
+
406
+    VarMapT::iterator it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_LOCAL_PARTY);
407
+    if (it != sc_sess->var.end())
408
+      peer->setLocalParty(it->second, it->second);
409
+
410
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_REMOTE_PARTY);
411
+    if (it != sc_sess->var.end())
412
+      peer->setRemoteParty(it->second, it->second);
413
+
414
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_HDRS);
415
+    if (it != sc_sess->var.end())
416
+      hdrs = it->second;
417
+
418
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_OUTBOUND_PROXY);
419
+    if (it != sc_sess->var.end())
420
+      p.outbound_proxy = it->second;
421
+
422
+    it = sc_sess->var.find(varname+"." DSM_SBC_PARAM_ADDCALLEE_RTP_MODE);
423
+    if (it != sc_sess->var.end()) {
424
+      if (it->second == "RTP_Direct") {
425
+	rtp_mode = AmB2BSession::RTP_Direct;
426
+      } else if (it->second == "RTP_Relay") {
427
+	rtp_mode = AmB2BSession::RTP_Relay;
428
+      } else if (it->second == "RTP_Transcoding") {
429
+	rtp_mode = AmB2BSession::RTP_Transcoding;
430
+      } else {
431
+	WARN("Unknown rtp_mode '%s', using this leg's mode\n", it->second.c_str());
432
+      }
433
+    }
434
+
435
+    sbc_call_leg->addCallee(peer, hdrs, rtp_mode);
436
+  }
437
+
438
+} EXEC_ACTION_END;
Browse code

sbc:dsm: support for reliable B2B events

sbc.relayReliableEvent(paramlist, processed_paramlist, unprocessed_paramlist) - relay reliable Event
if processed (#processed=true in other leg), event is sent back with processed_paramlist parameters,
if unprocessed, event is sent back with unprocessed_paramlist parameters
Example:
set($fwd_param1="this parameter goes fwd");
set($fwd_param2="this parameter goes fwd, too");
set($bck_param1="this parameter goes back if processed");
set($bck_param2="this parameter goes back if processed, too");
set($bck_unp_param1="this parameter goes back if not processed");
set($bck_unp_param2="this parameter goes back if not processed, too");
sbc.relayReliableEvent(fwd_param1;fwd_param2, bck_param1;bck_param2, bck_unp_param1;bck_unp_param2);

...

transition "B2B event" RUN - B2Bevent / {
logParams(3);
set(#processed="true");
} -> RUN;

Stefan Sayer authored on 04/11/2013 12:52:03
Showing 1 changed files
... ...
@@ -50,6 +50,7 @@ MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
50 50
   DEF_CMD("sbc.resumeHeld", MODSBCActionResumeHeld);
51 51
 
52 52
   DEF_CMD("sbc.getCallStatus", MODSBCActionGetCallStatus);
53
+  DEF_CMD("sbc.relayReliableEvent", MODSBCActionB2BRelayReliable);
53 54
 
54 55
 } MOD_ACTIONEXPORT_END;
55 56
 
... ...
@@ -317,3 +318,52 @@ EXEC_ACTION_START(MODSBCActionGetCallStatus) {
317 318
   sc_sess->var[varname] = call_leg->getCallStatusStr();
318 319
   DBG("set $%s='%s'\n", varname.c_str(), sc_sess->var[varname].c_str());
319 320
 } EXEC_ACTION_END;
321
+
322
+void setReliableEventParameters(const DSMSession* sc_sess, const string& var, VarMapT& params) {
323
+  vector<string> vars = explode(var, ";");
324
+  for (vector<string>::iterator it = vars.begin(); it != vars.end(); it++) {
325
+    string varname = *it;
326
+
327
+    if (varname.length() && varname[varname.length()-1]=='.') {
328
+      DBG("adding postEvent param %s (struct)\n", varname.c_str());
329
+
330
+      map<string, string>::const_iterator lb = sc_sess->var.lower_bound(varname);
331
+      while (lb != sc_sess->var.end()) {
332
+	if ((lb->first.length() < varname.length()) ||
333
+	    strncmp(lb->first.c_str(), varname.c_str(), varname.length()))
334
+	  break;
335
+	params[lb->first] = lb->second;
336
+	lb++;
337
+      }
338
+    } else {
339
+      VarMapT::const_iterator v_it = sc_sess->var.find(varname);
340
+      if (v_it != sc_sess->var.end()) {
341
+	DBG("adding reliableEvent param %s=%s\n",
342
+	    it->c_str(), v_it->second.c_str());
343
+	params[varname] = v_it->second;
344
+      }
345
+    }
346
+  }
347
+}
348
+
349
+CONST_ACTION_2P(MODSBCActionB2BRelayReliable, ',', false);
350
+EXEC_ACTION_START(MODSBCActionB2BRelayReliable) {
351
+  GET_CALL_LEG(B2BRelayReliable);
352
+  string ev_params = par1;
353
+  vector<string> success_params = explode(par2, ","); // q&d...
354
+  B2BEvent* processed = new B2BEvent(E_B2B_APP, B2BEvent::B2BApplication);
355
+  if (success_params.size()) {
356
+    setReliableEventParameters(sc_sess, trim(success_params[0], " "), processed->params);
357
+  }
358
+  B2BEvent* unprocessed = new B2BEvent(E_B2B_APP, B2BEvent::B2BApplication);
359
+  if (success_params.size() > 1) {
360
+    DBG("p='%s'\n", success_params[1].c_str());
361
+    setReliableEventParameters(sc_sess, trim(success_params[1], " "), unprocessed->params);
362
+  }
363
+
364
+  ReliableB2BEvent* rel_b2b_ev = new ReliableB2BEvent(E_B2B_APP, B2BEvent::B2BApplication, processed, unprocessed);
365
+  setReliableEventParameters(sc_sess, ev_params, rel_b2b_ev->params);
366
+
367
+  rel_b2b_ev->setSender(call_leg->getLocalTag());
368
+  call_leg->relayEvent(rel_b2b_ev);
369
+} EXEC_ACTION_END;
Browse code

sbc:dsm:use $var in getCallStatus

Stefan Sayer authored on 02/11/2013 15:30:46
Showing 1 changed files
... ...
@@ -311,7 +311,9 @@ EXEC_ACTION_START(MODSBCActionResumeHeld) {
311 311
 
312 312
 EXEC_ACTION_START(MODSBCActionGetCallStatus) {
313 313
   GET_CALL_LEG(GetCallStatus);
314
-  string varname = resolveVars(arg, sess, sc_sess, event_params);
314
+  string varname = arg;
315
+  if (varname.size() && varname[0] == '$')
316
+    varname.erase(0, 1);
315 317
   sc_sess->var[varname] = call_leg->getCallStatusStr();
316 318
   DBG("set $%s='%s'\n", varname.c_str(), sc_sess->var[varname].c_str());
317 319
 } EXEC_ACTION_END;
Browse code

sbc:dsm: added call status param

Stefan Sayer authored on 02/11/2013 15:18:27
Showing 1 changed files
... ...
@@ -49,6 +49,7 @@ MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
49 49
   DEF_CMD("sbc.putOnHold", MODSBCActionPutOnHold);
50 50
   DEF_CMD("sbc.resumeHeld", MODSBCActionResumeHeld);
51 51
 
52
+  DEF_CMD("sbc.getCallStatus", MODSBCActionGetCallStatus);
52 53
 
53 54
 } MOD_ACTIONEXPORT_END;
54 55
 
... ...
@@ -308,5 +309,9 @@ EXEC_ACTION_START(MODSBCActionResumeHeld) {
308 309
   call_leg->resumeHeld(send_reinvite == DSM_TRUE);
309 310
 } EXEC_ACTION_END;
310 311
 
311
-
312
-
312
+EXEC_ACTION_START(MODSBCActionGetCallStatus) {
313
+  GET_CALL_LEG(GetCallStatus);
314
+  string varname = resolveVars(arg, sess, sc_sess, event_params);
315
+  sc_sess->var[varname] = call_leg->getCallStatusStr();
316
+  DBG("set $%s='%s'\n", varname.c_str(), sc_sess->var[varname].c_str());
317
+} EXEC_ACTION_END;
Browse code

sbc:dsm: first version of DSM for SBC (wip)

allows the SBC to be controlled by DSM scripts
using the extended call control API.

Stefan Sayer authored on 02/11/2013 14:05:54
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,312 @@
1
+/*
2
+ * Copyright (C) 2013 Stefan Sayer
3
+ *
4
+ * This file is part of SEMS, a free SIP media server.
5
+ *
6
+ * SEMS is free software; you can redistribute it and/or modify
7
+ * it under the terms of the GNU General Public License as published by
8
+ * the Free Software Foundation; either version 2 of the License, or
9
+ * (at your option) any later version. This program is released under
10
+ * the GPL with the additional exemption that compiling, linking,
11
+ * and/or using OpenSSL is allowed.
12
+ *
13
+ * For a license to use the SEMS software under conditions
14
+ * other than those described here, or to purchase support for this
15
+ * software, please contact iptel.org by e-mail at the following addresses:
16
+ *    info@iptel.org
17
+ *
18
+ * SEMS is distributed in the hope that it will be useful,
19
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
+ * GNU General Public License for more details.
22
+ *
23
+ * You should have received a copy of the GNU General Public License 
24
+ * along with this program; if not, write to the Free Software 
25
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
+ */
27
+#include "ModSbc.h"
28
+#include "log.h"
29
+#include "AmUtils.h"
30
+
31
+#include "DSMCoreModule.h"
32
+
33
+#include "SBCCallProfile.h"
34
+#include "SBCDSMParams.h"
35
+#include "SBCCallLeg.h"
36
+
37
+SC_EXPORT(MOD_CLS_NAME);
38
+
39
+int MOD_CLS_NAME::preload() {
40
+  DBG("initializing mod_sbc...\n");
41
+  return 0;
42
+}
43
+
44
+MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
45
+  DEF_CMD("sbc.profileSet", MODSBCActionProfileSet);
46
+
47
+  DEF_CMD("sbc.stopCall", MODSBCActionStopCall);
48
+  DEF_CMD("sbc.disconnect", MODSBCActionDisconnect);
49
+  DEF_CMD("sbc.putOnHold", MODSBCActionPutOnHold);
50
+  DEF_CMD("sbc.resumeHeld", MODSBCActionResumeHeld);
51
+
52
+
53
+} MOD_ACTIONEXPORT_END;
54
+
55
+MOD_CONDITIONEXPORT_BEGIN(MOD_CLS_NAME) {
56
+  if (cmd == "legStateChange")
57
+    return new TestDSMCondition(params, DSMCondition::LegStateChange);
58
+
59
+  if (cmd == "bLegRefused")
60
+    return new TestDSMCondition(params, DSMCondition::BLegRefused);
61
+
62
+  // HOLD related
63
+  if (cmd == "PutOnHold")
64
+    return new TestDSMCondition(params, DSMCondition::PutOnHold);
65
+
66
+  if (cmd == "ResumeHeld")
67
+    return new TestDSMCondition(params, DSMCondition::ResumeHeld);
68
+
69
+  if (cmd == "CreateHoldRequest")
70
+    return new TestDSMCondition(params, DSMCondition::CreateHoldRequest);
71
+
72
+  if (cmd == "HandleHoldReply")
73
+    return new TestDSMCondition(params, DSMCondition::HandleHoldReply);
74
+
75
+  // simple relay related
76
+  if (cmd == "RelayInit")
77
+    return new TestDSMCondition(params, DSMCondition::RelayInit);
78
+
79
+  if (cmd == "RelayInitUAC")
80
+    return new TestDSMCondition(params, DSMCondition::RelayInitUAC);
81
+
82
+  if (cmd == "RelayInitUAS")
83
+    return new TestDSMCondition(params, DSMCondition::RelayInitUAS);
84
+
85
+  if (cmd == "RelayFinalize")
86
+    return new TestDSMCondition(params, DSMCondition::RelayFinalize);
87
+
88
+  if (cmd == "RelayOnSipRequest")
89
+    return new TestDSMCondition(params, DSMCondition::RelayOnSipRequest);
90
+
91
+  if (cmd == "RelayOnSipReply")
92
+    return new TestDSMCondition(params, DSMCondition::RelayOnSipReply);
93
+
94
+  if (cmd == "RelayOnB2BRequest")
95
+    return new TestDSMCondition(params, DSMCondition::RelayOnB2BRequest);
96
+
97
+  if (cmd == "RelayOnB2BReply")
98
+    return new TestDSMCondition(params, DSMCondition::RelayOnB2BReply);
99
+
100
+  if (cmd == "RelayOnB2BReply")
101
+    return new TestDSMCondition(params, DSMCondition::RelayOnB2BReply);
102
+
103
+  if (cmd == "sbc.isALeg")
104
+    return new SBCIsALegCondition(params, false);
105
+
106
+  if (cmd == "sbc.isOnHold")
107
+    return new SBCIsOnHoldCondition(params, false);
108
+
109
+} MOD_CONDITIONEXPORT_END
110
+
111
+
112
+MATCH_CONDITION_START(SBCIsALegCondition) {
113
+  SBCCallLeg* call_leg = dynamic_cast<SBCCallLeg*>(sess);
114
+  if (NULL == call_leg) {
115
+    DBG("script writer error: DSM condition sbc.isALeg"
116
+	" used without call leg\n");
117
+    return false;
118
+  }
119
+
120
+  bool b = call_leg->isALeg();
121
+  bool res = inv ^ b;
122
+  DBG("SBC: isALeg() == %s (res = %s)\n",
123
+      b ? "true":"false", res ? "true":"false");
124
+  return res;
125
+} MATCH_CONDITION_END;
126
+
127
+MATCH_CONDITION_START(SBCIsOnHoldCondition) {
128
+  SBCCallLeg* call_leg = dynamic_cast<SBCCallLeg*>(sess);
129
+  if (NULL == call_leg) {
130
+    DBG("script writer error: DSM condition sbc.isOnHold"
131
+	" used without call leg\n");
132
+    return false;
133
+  }
134
+
135
+  bool b = call_leg->isOnHold();
136
+  bool res = inv ^ b;
137
+  DBG("SBC: isOnHold() == %s (res = %s)\n",
138
+      b ? "true":"false", res ? "true":"false");
139
+  return res;
140
+} MATCH_CONDITION_END;
141
+
142
+
143
+#define ACTION_GET_PROFILE			\
144
+  SBCCallProfile* profile = NULL;					\
145
+  AVarMapT::iterator it = sc_sess->avar.find(DSM_SBC_AVAR_PROFILE);	\
146
+  if (it != sc_sess->avar.end()) {					\
147
+    profile = dynamic_cast<SBCCallProfile*>(it->second.asObject());	\
148
+  }									\
149
+  if (NULL == profile) {						\
150
+  SBCCallLeg* call = dynamic_cast<SBCCallLeg*>(sess);			\
151
+  if (NULL !=  call)							\
152
+    profile = &call->getCallProfile();					\
153
+  }									\
154
+									\
155
+  if (NULL == profile) {						\
156
+    ERROR("internal: Call profile object not found\n");			\
157
+    EXEC_ACTION_STOP;							\
158
+  }
159
+
160
+CONST_ACTION_2P(MODSBCActionProfileSet, ',', false);
161
+EXEC_ACTION_START(MODSBCActionProfileSet) {
162
+  string profile_param = resolveVars(par1, sess, sc_sess, event_params);
163
+  string value = resolveVars(par2, sess, sc_sess, event_params);
164
+
165
+  ACTION_GET_PROFILE;
166
+
167
+#define SET_TO_CALL_PROFILE(cfgparam, member)		\
168
+  if (profile_param == cfgparam) {			\
169
+    profile->member=value;				\
170
+    DBG(cfgparam " set to '%s'\n", value.c_str());	\
171
+    EXEC_ACTION_STOP;					\
172
+  }
173
+
174
+#define SET_TO_CALL_PROFILE_OPTION(cfgparam, member)			\
175
+  if (profile_param == cfgparam) {					\
176
+    profile->member=(value == "true");					\
177
+    DBG(cfgparam " set to '%s'\n", profile->member?"true":"false");	\
178
+    EXEC_ACTION_STOP;							\
179
+  }
180
+
181
+  switch (profile_param.length()) {
182
+  case 2: 
183
+  SET_TO_CALL_PROFILE("To", to);
184
+  break;
185
+
186
+  case 4:
187
+  SET_TO_CALL_PROFILE("RURI", ruri);
188
+  SET_TO_CALL_PROFILE("From", from);
189
+  break;
190
+
191
+
192
+  case 7:
193
+  SET_TO_CALL_PROFILE("Call-ID", callid);
194
+  break;
195
+
196
+  case 8:
197
+  SET_TO_CALL_PROFILE("next_hop", next_hop);
198
+  break;
199
+
200
+  case 9:
201
+  SET_TO_CALL_PROFILE("RURI_host", ruri_host);
202
+  break;
203
+
204
+
205
+  case 11:
206
+  SET_TO_CALL_PROFILE("refuse_with", refuse_with);
207
+  break;
208
+
209
+  default:
210
+
211
+  SET_TO_CALL_PROFILE("outbound_proxy", outbound_proxy);
212
+  SET_TO_CALL_PROFILE_OPTION("force_outbound_proxy", force_outbound_proxy);
213
+
214
+  SET_TO_CALL_PROFILE("aleg_outbound_proxy", aleg_outbound_proxy);
215
+  SET_TO_CALL_PROFILE_OPTION("aleg_force_outbound_proxy", aleg_force_outbound_proxy);
216
+
217
+  SET_TO_CALL_PROFILE_OPTION("next_hop_1st_req", next_hop_1st_req);
218
+  SET_TO_CALL_PROFILE_OPTION("patch_ruri_next_hop", patch_ruri_next_hop);
219
+
220
+  SET_TO_CALL_PROFILE("aleg_next_hop", aleg_next_hop);
221
+
222
+  // TODO: message_filter
223
+  // TODO: header_filter
224