Browse code

merged from 'master'.

Raphael Coeffic authored on 04/01/2011 13:41:17
Showing 107 changed files
... ...
@@ -1,13 +1,16 @@
1
-*~
1
+*.a
2 2
 *.d
3 3
 *.o
4
-*.a
5
-*.so
6 4
 *.pyc
7 5
 *.pyo
6
+*.so
7
+*~
8
+apps/py_sems/sip/*.cpp
9
+apps/py_sems/sip/*.h
10
+apps/py_sems/sip/Makefile.gen
11
+core/etc/*.conf
12
+core/etc/*.template
8 13
 getarch
9 14
 getos
10 15
 sems
11 16
 sems-stats
12
-core/etc/*.conf
13
-core/etc/*.template
... ...
@@ -89,6 +89,7 @@ SET(CMAKE_VERBOSE_MAKEFILE ON)
89 89
 #   (which means that current debian and gentoo packages don't work)
90 90
 IF(SEMS_USE_SPANDSP)
91 91
 	FIND_PACKAGE(Spandsp REQUIRED)
92
+	ADD_DEFINITIONS(-DUSE_SPANDSP -D__STDC_LIMIT_MACROS)
92 93
 	MESSAGE(STATUS "Using spandsp: YES")
93 94
 ELSE(SEMS_USE_SPANDSP)
94 95
 	MESSAGE(STATUS "Using spandsp: NO (default)")
... ...
@@ -98,6 +99,7 @@ ENDIF(SEMS_USE_SPANDSP)
98 99
 # (see http://www.mega-nerd.com/SRC/)
99 100
 IF(SEMS_USE_LIBSAMPLERATE)
100 101
 	FIND_PACKAGE(Libsamplerate REQUIRED)
102
+	ADD_DEFINITIONS(-DUSE_LIBSAMPLERATE)
101 103
 	MESSAGE(STATUS "Using libsamplerate: YES")
102 104
 ELSE(SEMS_USE_LIBSAMPLERATE)
103 105
 	MESSAGE(STATUS "Using libsamplerate: NO (default)")
... ...
@@ -137,6 +139,7 @@ ELSE(SEMS_USE_MONITORING)
137 139
 ENDIF(SEMS_USE_MONITORING)
138 140
 
139 141
 IF(SEMS_USE_IPV6)
142
+	ADD_DEFINITIONS(-DSUPPORT_IPV6)
140 143
 	MESSAGE(STATUS "Enable IPv6 support: YES")
141 144
 ELSE(SEMS_USE_IPV6)
142 145
 	MESSAGE(STATUS "Enable IPv6 support: NO (default)")
... ...
@@ -56,7 +56,6 @@ EXPORT_SESSION_FACTORY(AnnRecorderFactory,MOD_NAME);
56 56
 string AnnRecorderFactory::AnnouncePath;
57 57
 string AnnRecorderFactory::DefaultAnnounce;
58 58
 bool   AnnRecorderFactory::SimpleMode=false;
59
-AmDynInvokeFactory* AnnRecorderFactory::user_timer_fact = NULL;
60 59
 AmDynInvokeFactory* AnnRecorderFactory::message_storage_fact = NULL;
61 60
 
62 61
 const char* MsgStrError(int e) {
... ...
@@ -106,8 +105,7 @@ int AnnRecorderFactory::onLoad()
106 105
   AM_PROMPT_END(prompts, cfg, MOD_NAME);
107 106
 
108 107
 
109
-  user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer");
110
-  if(!user_timer_fact) {
108
+  if (!AmSession::timersSupported()) {
111 109
     ERROR("sorry, could not load user_timer from session_timer plug-in\n");
112 110
     return -1;
113 111
   }
... ...
@@ -253,12 +251,6 @@ AnnRecorderDialog::AnnRecorderDialog(const map<string, string>& params,
253 251
     prompts(prompts), cred(credentials),
254 252
     playlist(this)
255 253
 {
256
-  user_timer = AnnRecorderFactory::user_timer_fact->getInstance();
257
-  if(!user_timer) {
258
-    ERROR("could not get a user timer reference\n");
259
-    throw AmSession::Exception(500,"could not get a timer");
260
-  }
261
-
262 254
   msg_storage = AnnRecorderFactory::message_storage_fact->getInstance();
263 255
   if(!msg_storage){
264 256
     ERROR("could not get a message storage reference\n");
... ...
@@ -310,9 +302,7 @@ void AnnRecorderDialog::onDtmf(int event, int duration_msec) {
310 302
   DBG("DTMF %d, %d\n", event, duration_msec);
311 303
   // remove timer
312 304
   try {
313
-  AmArg di_args,ret;
314
-  di_args.push(getLocalTag().c_str());
315
-  user_timer->invoke("removeUserTimers", di_args, ret);
305
+    removeTimers();
316 306
   } catch(...) {
317 307
     ERROR("Exception caught calling mod api\n");
318 308
   }
... ...
@@ -425,22 +415,14 @@ void AnnRecorderDialog::process(AmEvent* event)
425 415
     if ((pl_ev->event_id == SEP_MSG_BEGIN) && 
426 416
 	(S_WAIT_START == state)) {
427 417
       // start timer
428
-      AmArg di_args,ret;
429
-      di_args.push(TIMERID_START_TIMER);
430
-      di_args.push(START_RECORDING_TIMEOUT);  // in seconds
431
-      di_args.push(getLocalTag().c_str());
432
-      user_timer->invoke("setTimer", di_args, ret);
418
+      setTimer(TIMERID_START_TIMER, START_RECORDING_TIMEOUT);
433 419
       return;
434 420
     }
435 421
 
436 422
     if ((pl_ev->event_id == SEP_CONFIRM_BEGIN) && 
437 423
 	(S_CONFIRM == state)) {
438 424
       // start timer
439
-      AmArg di_args,ret;
440
-      di_args.push(TIMERID_CONFIRM_TIMER);
441
-      di_args.push(CONFIRM_RECORDING_TIMEOUT);  // in seconds
442
-      di_args.push(getLocalTag().c_str());
443
-      user_timer->invoke("setTimer", di_args, ret);
425
+      setTimer(TIMERID_CONFIRM_TIMER, CONFIRM_RECORDING_TIMEOUT);
444 426
       return;
445 427
     }
446 428
     return;
... ...
@@ -65,7 +65,6 @@ class AnnRecorderFactory: public AmSessionFactory
65 65
   AmPromptCollection prompts;
66 66
 
67 67
 public:  
68
-  static AmDynInvokeFactory* user_timer_fact; 
69 68
   static AmDynInvokeFactory* message_storage_fact; 
70 69
 
71 70
   static string AnnouncePath;
... ...
@@ -95,7 +94,6 @@ class AnnRecorderDialog : public AmSession,
95 94
 
96 95
   string msg_filename; // recorded file
97 96
 
98
-  AmDynInvoke* user_timer;
99 97
   AmDynInvoke* msg_storage;
100 98
 
101 99
   std::auto_ptr<UACAuthCred> cred;
... ...
@@ -43,7 +43,6 @@ EXPORT_SESSION_FACTORY(AuthB2BFactory,MOD_NAME);
43 43
 
44 44
 AuthB2BFactory::AuthB2BFactory(const string& _app_name)
45 45
 : AmSessionFactory(_app_name)
46
-// , user_timer_fact(NULL)
47 46
 {
48 47
 }
49 48
 
... ...
@@ -61,31 +60,18 @@ int AuthB2BFactory::onLoad()
61 60
      pwd = cfg.getParameter("pwd");
62 61
    }
63 62
 
64
-//   user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer");
65
-//   if(!user_timer_fact) {
66
-//     ERROR("could not load user_timer from session_timer plug-in\n");
67
-//     return -1;
68
-//   }
69
-
70 63
   return 0;
71 64
 }
72 65
 
73 66
 
74 67
 AmSession* AuthB2BFactory::onInvite(const AmSipRequest& req)
75 68
 {
76
-//   AmDynInvoke* user_timer = user_timer_fact->getInstance();
77
-//   if(!user_timer) {
78
-//     ERROR("could not get a user timer reference\n");
79
-//     throw AmSession::Exception(500,"could not get a user timer reference");
80
-//   }
81
-
82
-  return new AuthB2BDialog(); //user_timer);
69
+  return new AuthB2BDialog();
83 70
 }
84 71
 
85 72
 
86
-AuthB2BDialog::AuthB2BDialog() // AmDynInvoke* user_timer)
73
+AuthB2BDialog::AuthB2BDialog()
87 74
 : m_state(BB_Init),
88
-  //m_user_timer(user_timer),
89 75
   AmB2BCallerSession()
90 76
 
91 77
 {
... ...
@@ -187,11 +173,7 @@ bool AuthB2BDialog::onOtherReply(const AmSipReply& reply)
187 173
         setInOut(NULL, NULL);
188 174
 
189 175
 //         // set the call timer
190
-//         AmArg di_args,ret;
191
-//         di_args.push(TIMERID_CREDIT_TIMEOUT);
192
-//         di_args.push(m_credit);  // in seconds
193
-//         di_args.push(dlg.local_tag.c_str());
194
-//         m_user_timer->invoke("setTimer", di_args, ret);
176
+//      setTimer(TIMERID_CREDIT_TIMEOUT, m_credit);
195 177
       }
196 178
     }
197 179
     else if(reply.code == 487 && (dlg.getStatus() < AmSipDialog::Connected)) {
... ...
@@ -35,7 +35,6 @@ using std::string;
35 35
 
36 36
 class AuthB2BFactory: public AmSessionFactory
37 37
 {
38
-/*   AmDynInvokeFactory* user_timer_fact; */
39 38
 
40 39
  public:
41 40
   AuthB2BFactory(const string& _app_name);
... ...
@@ -65,11 +64,9 @@ class AuthB2BDialog : public AmB2BCallerSession
65 64
   string from;
66 65
   string to;
67 66
   
68
-/*   AmDynInvoke* m_user_timer; */
69
-
70 67
  public:
71 68
 
72
-  AuthB2BDialog(); //AmDynInvoke* user_timer);
69
+  AuthB2BDialog();
73 70
   ~AuthB2BDialog();
74 71
   
75 72
   void process(AmEvent* ev);
... ...
@@ -46,8 +46,7 @@ bool         CallTimerFactory::UseAppParam = true;
46 46
 EXPORT_SESSION_FACTORY(CallTimerFactory,MOD_NAME);
47 47
 
48 48
 CallTimerFactory::CallTimerFactory(const string& _app_name)
49
-: AmSessionFactory(_app_name), 
50
-  user_timer_fact(NULL)
49
+: AmSessionFactory(_app_name)
51 50
 {
52 51
 }
53 52
 
... ...
@@ -67,9 +66,8 @@ int CallTimerFactory::onLoad()
67 66
     UseAppParam = (cfg.getParameter("use_app_param") == "yes");
68 67
   }
69 68
 
70
-  user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer");
71
-  if(!user_timer_fact) {
72
-    ERROR("could not load user_timer from session_timer plug-in\n");
69
+  if (!AmSession::timersSupported()) {
70
+    ERROR("load session_timer plug-in for timers\n");
73 71
     return -1;
74 72
   }
75 73
 
... ...
@@ -80,11 +78,6 @@ int CallTimerFactory::onLoad()
80 78
 AmSession* CallTimerFactory::onInvite(const AmSipRequest& req)
81 79
 {
82 80
   DBG(" *** creating new call timer session ***\n");
83
-  AmDynInvoke* user_timer = user_timer_fact->getInstance();
84
-  if(!user_timer) {
85
-    ERROR("could not get a user timer reference\n");
86
-     throw AmSession::Exception(500,"could not get a user timer reference");
87
-  }
88 81
 
89 82
   string app_param = getHeader(req.hdrs, PARAM_HDR, true);
90 83
 
... ...
@@ -107,15 +100,13 @@ AmSession* CallTimerFactory::onInvite(const AmSipRequest& req)
107 100
 
108 101
   DBG("using call timer %d seconds\n", call_time);
109 102
 
110
-  return new CallTimerDialog(user_timer, call_time);
103
+  return new CallTimerDialog(call_time);
111 104
 }
112 105
 
113 106
 
114
-CallTimerDialog::CallTimerDialog(AmDynInvoke* user_timer,
115
-				 unsigned int call_time)
107
+CallTimerDialog::CallTimerDialog(unsigned int call_time)
116 108
 : m_state(BB_Init),
117 109
   call_time(call_time),
118
-  m_user_timer(user_timer),
119 110
   AmB2BCallerSession()
120 111
 
121 112
 {
... ...
@@ -185,11 +176,7 @@ bool CallTimerDialog::onOtherReply(const AmSipReply& reply)
185 176
         setInOut(NULL, NULL);
186 177
 	// startAccounting();
187 178
 	// set the call timer
188
-	AmArg di_args,ret;
189
-	di_args.push(TIMERID_CALL_TIMER);
190
-	di_args.push((int)call_time);  // in seconds
191
-	di_args.push(dlg.local_tag.c_str());
192
-        m_user_timer->invoke("setTimer", di_args, ret);
179
+	setTimer(TIMERID_CALL_TIMER, call_time);
193 180
       }
194 181
     }
195 182
     else if(reply.code == 487 && dlg.getStatus() < AmSipDialog::Connected) {
... ...
@@ -36,8 +36,6 @@ using std::string;
36 36
 class CallTimerFactory: public AmSessionFactory
37 37
 {
38 38
  public:
39
-  AmDynInvokeFactory* user_timer_fact; 
40
-
41 39
   static unsigned int DefaultCallTimer; 
42 40
   static bool UseAppParam;
43 41
 
... ...
@@ -59,14 +57,11 @@ class CallTimerDialog : public AmB2BCallerSession
59 57
 
60 58
   int m_state;
61 59
   
62
-  AmDynInvoke* m_user_timer;
63
-
64 60
   unsigned int call_time;
65 61
 
66 62
  public:
67 63
 
68
-  CallTimerDialog(AmDynInvoke* user_timer, 
69
-		  unsigned int call_time);
64
+  CallTimerDialog(unsigned int call_time);
70 65
   ~CallTimerDialog();
71 66
   
72 67
   void process(AmEvent* ev);
... ...
@@ -544,12 +544,12 @@ void AmArg2DSMStrMap(const AmArg& arg,
544 544
     if (it->second.getType() == AmArg::CStr)
545 545
       vars[it->first] = it->second.asCStr();
546 546
     else if (it->second.getType() == AmArg::Array) {
547
-      vars[it->first+"_size"] = int2str(it->second.size());
547
+      vars[it->first+"_size"] = int2str((unsigned int)it->second.size());
548 548
       for (size_t i=0;i<it->second.size();i++) {
549 549
 	if (it->second.get(i).getType() == AmArg::CStr)
550
-	  vars[it->first+"_"+int2str(i)] = it->second.get(i).asCStr();
550
+	  vars[it->first+"_"+int2str((unsigned int)i)] = it->second.get(i).asCStr();
551 551
 	else
552
-	  vars[it->first+"_"+int2str(i)] = AmArg::print(it->second.get(i));
552
+	  vars[it->first+"_"+int2str((unsigned int)i)] = AmArg::print(it->second.get(i));
553 553
       }
554 554
     } else {
555 555
       vars[it->first] = AmArg::print(it->second);	
... ...
@@ -349,6 +349,10 @@ void DSMCall::onSystemEvent(AmSystemEvent* ev) {
349 349
   }
350 350
 }
351 351
 
352
+void DSMCall::onBeforeDestroy() {
353
+  engine.onBeforeDestroy(this, this);
354
+}
355
+
352 356
 void DSMCall::process(AmEvent* event)
353 357
 {
354 358
 
... ...
@@ -81,6 +81,7 @@ public:
81 81
   void onCancel();
82 82
   void onBye(const AmSipRequest& req);
83 83
   void onDtmf(int event, int duration_msec);
84
+  void onBeforeDestroy();
84 85
 
85 86
   void onSipRequest(const AmSipRequest& req);
86 87
   void onSipReply(const AmSipReply& reply, AmSipDialog::Status old_dlg_status);
... ...
@@ -79,6 +79,7 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) {
79 79
   DEF_CMD("eval", SCEvalAction);
80 80
   DEF_CMD("setVar", SCSetVarAction);
81 81
   DEF_CMD("var", SCGetVarAction);
82
+  DEF_CMD("param", SCGetParamAction);
82 83
   DEF_CMD("append", SCAppendAction);
83 84
   DEF_CMD("substr", SCSubStrAction);
84 85
   DEF_CMD("inc", SCIncAction);
... ...
@@ -627,6 +628,30 @@ EXEC_ACTION_START(SCSetVarAction) {
627 628
       var_name.c_str(), sc_sess->var[var_name].c_str());
628 629
 } EXEC_ACTION_END;
629 630
 
631
+CONST_ACTION_2P(SCGetParamAction,'=', false);
632
+EXEC_ACTION_START(SCGetParamAction){
633
+
634
+  string dst_var_name = (par1.length() && par1[0] == '$')?
635
+    par1.substr(1) : par1;
636
+  string param_name = resolveVars(par2, sess, sc_sess, event_params);
637
+  
638
+  DBG("param_name = %s, dst = %s\n", param_name.c_str(), dst_var_name.c_str());
639
+
640
+  if (NULL==event_params) {
641
+    sc_sess->var[dst_var_name] = "";
642
+    EXEC_ACTION_STOP;
643
+  }
644
+
645
+  map<string, string>::iterator it = event_params->find(param_name);
646
+  if (it != event_params->end()) {
647
+    sc_sess->var[dst_var_name] = it->second;
648
+  } else {
649
+    sc_sess->var[dst_var_name] = "";
650
+  }
651
+  
652
+  DBG("set $%s='%s'\n", 
653
+      dst_var_name.c_str(), sc_sess->var[dst_var_name].c_str());
654
+} EXEC_ACTION_END;
630 655
 
631 656
 CONST_ACTION_2P(SCGetVarAction,'=', false);
632 657
 EXEC_ACTION_START(SCGetVarAction){
... ...
@@ -756,30 +781,13 @@ EXEC_ACTION_START(SCSetTimerAction) {
756 781
     EXEC_ACTION_STOP;
757 782
   }
758 783
 
759
-  DBG("setting timer %u with timeout %u\n", timerid, timeout);
760
-  AmDynInvokeFactory* user_timer_fact = 
761
-    AmPlugIn::instance()->getFactory4Di("user_timer");
762
-
763
-  if(!user_timer_fact) {
764
-    ERROR("load sess_timer module for timers.\n");
765
-    sc_sess->SET_ERRNO(DSM_ERRNO_CONFIG);
766
-    sc_sess->SET_STRERROR("load sess_timer module for timers.\n");
767
-    EXEC_ACTION_STOP;
768
-  }
769
-  AmDynInvoke* user_timer = user_timer_fact->getInstance();
770
-  if(!user_timer) {
771
-    ERROR("load sess_timer module for timers.\n");
784
+  if (!sess->setTimer(timerid, timeout)) {
785
+    ERROR("load session_timer module for timers.\n");
772 786
     sc_sess->SET_ERRNO(DSM_ERRNO_CONFIG);
773 787
     sc_sess->SET_STRERROR("load sess_timer module for timers.\n");
774 788
     EXEC_ACTION_STOP;
775 789
   }
776 790
 
777
-  AmArg di_args,ret;
778
-  di_args.push((int)timerid);
779
-  di_args.push((int)timeout);      // in seconds
780
-  di_args.push(sess->getLocalTag().c_str());
781
-  user_timer->invoke("setTimer", di_args, ret);
782
-
783 791
   sc_sess->CLR_ERRNO;
784 792
 } EXEC_ACTION_END;
785 793
 
... ...
@@ -795,54 +803,26 @@ EXEC_ACTION_START(SCRemoveTimerAction) {
795 803
     return false;
796 804
   }
797 805
 
798
-  DBG("removing timer %u\n", timerid);
799
-  AmDynInvokeFactory* user_timer_fact = 
800
-    AmPlugIn::instance()->getFactory4Di("user_timer");
801
-
802
-  if(!user_timer_fact) {
806
+  if (!sess->removeTimer(timerid)) {
807
+    ERROR("load session_timer module for timers.\n");
803 808
     sc_sess->SET_ERRNO(DSM_ERRNO_CONFIG);
804
-    sc_sess->SET_STRERROR("load sess_timer module for timers.\n");
805
-    EXEC_ACTION_STOP;
806
-  }
807
-  AmDynInvoke* user_timer = user_timer_fact->getInstance();
808
-  if(!user_timer) {
809
-    sc_sess->SET_ERRNO(DSM_ERRNO_CONFIG);
810
-    sc_sess->SET_STRERROR("load sess_timer module for timers.\n");
809
+    sc_sess->SET_STRERROR("load session_timer module for timers.\n");
811 810
     EXEC_ACTION_STOP;
812 811
   }
813 812
 
814
-  AmArg di_args,ret;
815
-  di_args.push((int)timerid);
816
-  di_args.push(sess->getLocalTag().c_str());
817
-  user_timer->invoke("removeTimer", di_args, ret);
818
-
819 813
   sc_sess->CLR_ERRNO;
820 814
 } EXEC_ACTION_END;
821 815
 
822 816
 EXEC_ACTION_START(SCRemoveTimersAction) {
823 817
 
824
-
825 818
   DBG("removing timers for session %s\n", sess->getLocalTag().c_str());
826
-  AmDynInvokeFactory* user_timer_fact = 
827
-    AmPlugIn::instance()->getFactory4Di("user_timer");
828
-
829
-  if(!user_timer_fact) {
830
-    ERROR("load sess_timer module for timers.\n");
831
-    sc_sess->SET_ERRNO(DSM_ERRNO_CONFIG);
832
-    sc_sess->SET_STRERROR("load sess_timer module for timers.\n");
833
-    EXEC_ACTION_STOP;
834
-  }
835
-  AmDynInvoke* user_timer = user_timer_fact->getInstance();
836
-  if(!user_timer) {
819
+  if (!sess->removeTimers()) {
820
+    ERROR("load session_timer module for timers.\n");
837 821
     sc_sess->SET_ERRNO(DSM_ERRNO_CONFIG);
838 822
     sc_sess->SET_STRERROR("load sess_timer module for timers.\n");
839 823
     EXEC_ACTION_STOP;
840 824
   }
841 825
 
842
-  AmArg di_args,ret;
843
-  di_args.push(sess->getLocalTag().c_str());
844
-  user_timer->invoke("removeUserTimers", di_args, ret);
845
-
846 826
   sc_sess->CLR_ERRNO;
847 827
 } EXEC_ACTION_END;
848 828
 
... ...
@@ -908,7 +888,7 @@ bool TestDSMCondition::match(AmSession* sess, DSMSession* sc_sess, DSMCondition:
908 888
   string r;
909 889
   if (lhs.length() > 5 && 
910 890
       (lhs.substr(0, 4) == "len(") && lhs[lhs.length()-1] == ')') {
911
-    l = int2str(resolveVars(lhs.substr(4, lhs.length()-5), sess, sc_sess, event_params).length());
891
+    l = int2str((unsigned int)resolveVars(lhs.substr(4, lhs.length()-5), sess, sc_sess, event_params).length());
912 892
   } else {    
913 893
     l   = resolveVars(lhs, sess, sc_sess, event_params);
914 894
   }
... ...
@@ -1144,11 +1124,11 @@ EXEC_ACTION_START(SCDIAction) {
1144 1124
       for (size_t i=0;i<sc_sess->di_res.size();i++) {
1145 1125
 	switch (sc_sess->di_res.get(i).getType()) {
1146 1126
 	case AmArg::CStr: {
1147
-	  sc_sess->var["DI_res"+int2str(i)] = 
1127
+	  sc_sess->var["DI_res"+int2str((unsigned int)i)] =
1148 1128
 	    sc_sess->di_res.get(i).asCStr();
1149 1129
 	} break;
1150 1130
 	case AmArg::Int: {
1151
-	  sc_sess->var["DI_res"+int2str(i)] = 
1131
+	  sc_sess->var["DI_res"+int2str((unsigned int)i)] =
1152 1132
 	    int2str(sc_sess->di_res.get(i).asInt());
1153 1133
 	} break;
1154 1134
 	default: {
... ...
@@ -93,6 +93,7 @@ DEF_ACTION_1P(SCLogParamsAction);
93 93
 DEF_ACTION_1P(SCLogSelectsAction);
94 94
 DEF_ACTION_1P(SCLogAllAction);
95 95
 DEF_ACTION_2P(SCGetVarAction);
96
+DEF_ACTION_2P(SCGetParamAction);
96 97
 DEF_ACTION_2P(SCSetVarAction);
97 98
 DEF_ACTION_2P(SCPlayFileAction);
98 99
 DEF_ACTION_2P(SCPlayFileFrontAction);
... ...
@@ -51,6 +51,7 @@ class DSMModule {
51 51
 
52 52
   virtual int preload() { return 0; }
53 53
   virtual bool onInvite(const AmSipRequest& req, DSMSession* sess) { return true; }
54
+  virtual void onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) { }
54 55
 };
55 56
 
56 57
 typedef map<string,string> EventParamT;
... ...
@@ -218,6 +218,11 @@ bool DSMStateEngine::onInvite(const AmSipRequest& req, DSMSession* sess) {
218 218
 
219 219
   return res;
220 220
 }
221
+void DSMStateEngine::onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) {
222
+  for (vector<DSMModule*>::iterator it =
223
+	 mods.begin(); it != mods.end(); it++)
224
+    (*it)->onBeforeDestroy(sc_sess, sess);
225
+}
221 226
 
222 227
 bool DSMStateEngine::runactions(vector<DSMAction*>::iterator from, 
223 228
 				vector<DSMAction*>::iterator to, 
... ...
@@ -548,7 +553,7 @@ void varPrintArg(const AmArg& a, map<string, string>& dst, const string& name) {
548 553
     dst[name] = a.asCStr(); return;
549 554
   case AmArg::Array:
550 555
     for (size_t i = 0; i < a.size(); i ++)
551
-      varPrintArg(a.get(i), dst, name+"["+int2str(i)+"]");
556
+      varPrintArg(a.get(i), dst, name+"["+int2str((unsigned int)i)+"]");
552 557
     return;
553 558
   case AmArg::Struct:
554 559
     for (AmArg::ValueStruct::const_iterator it = a.asStruct()->begin();
... ...
@@ -249,6 +249,7 @@ class DSMStateEngine {
249 249
 
250 250
   /** @return whether call should be accepted */
251 251
   bool onInvite(const AmSipRequest& req, DSMSession* sess);
252
+  void onBeforeDestroy(DSMSession* sc_sess, AmSession* sess);
252 253
 };
253 254
 
254 255
 extern void varPrintArg(const AmArg& a, map<string, string>& dst, const string& name);
... ...
@@ -13,7 +13,8 @@ endif
13 13
 $(info exclude_dsm_modules: $(exclude_dsm_modules))
14 14
 dsm_modules = $(filter-out $(subst ;, ,$(exclude_dsm_modules))\
15 15
 		$(wildcard Makefile*) lib CMakeLists.txt, \
16
-		$(wildcard *) )
16
+		$(wildcard mod_*) )
17
+$(info dsm_modules: $(dsm_modules))
17 18
 
18 19
 .PHONY: all
19 20
 all: modules
20 21
new file mode 100644
... ...
@@ -0,0 +1,7 @@
1
+set (mod_groups_SRCS
2
+ModGroups.cpp
3
+)
4
+
5
+SET(sems_dsm_module_name mod_groups)
6
+INCLUDE(${CMAKE_SOURCE_DIR}/cmake/dsm.lib.rules.txt)
7
+
0 8
new file mode 100644
... ...
@@ -0,0 +1,10 @@
1
+plug_in_name = mod_groups
2
+
3
+DSMPATH ?= ../..
4
+
5
+module_ldflags = 
6
+module_cflags  = -DMOD_NAME=\"$(plug_in_name)\" -I$(DSMPATH)
7
+
8
+COREPATH ?=$(DSMPATH)/../../core
9
+lib_full_name = $(DSMPATH)/mods/lib/$(lib_name)
10
+include $(DSMPATH)/mods/Makefile.dsm_module
0 11
new file mode 100644
... ...
@@ -0,0 +1,175 @@
1
+/*
2
+ * Copyright (C) 2010 Stefan Sayer
3
+ * 
4
+ * Development of this module was sponsored by TelTech Systems Inc
5
+ * 
6
+ * This file is part of SEMS, a free SIP media server.
7
+ *
8
+ * SEMS is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version. This program is released under
12
+ * the GPL with the additional exemption that compiling, linking,
13
+ * and/or using OpenSSL is allowed.
14
+ *
15
+ * For a license to use the SEMS software under conditions
16
+ * other than those described here, or to purchase support for this
17
+ * software, please contact iptel.org by e-mail at the following addresses:
18
+ *    info@iptel.org
19
+ *
20
+ * SEMS is distributed in the hope that it will be useful,
21
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
+ * GNU General Public License for more details.
24
+ *
25
+ * You should have received a copy of the GNU General Public License 
26
+ * along with this program; if not, write to the Free Software 
27
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28
+ */
29
+
30
+#include "ModGroups.h"
31
+#include "log.h"
32
+#include "AmUtils.h"
33
+
34
+#include "DSMSession.h"
35
+#include "AmSession.h"
36
+#include "AmSessionContainer.h"
37
+
38
+SC_EXPORT(MOD_CLS_NAME);
39
+
40
+AmMutex GroupsModule::groups_mut;
41
+GroupMap GroupsModule::groups;
42
+GroupMap GroupsModule::groups_rev;
43
+
44
+
45
+MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
46
+
47
+  DEF_CMD("groups.join", GroupsJoinAction);
48
+  DEF_CMD("groups.leave", GroupsLeaveAction);
49
+  DEF_CMD("groups.leaveAll", GroupsLeaveAllAction);
50
+  // DEF_CMD("groups.get", GroupsGetAction);
51
+  // DEF_CMD("groups.getMembers", GroupsGetMembersAction);
52
+  DEF_CMD("groups.postEvent", GroupsPostEventAction);
53
+
54
+} MOD_ACTIONEXPORT_END;
55
+
56
+MOD_CONDITIONEXPORT_NONE(MOD_CLS_NAME);
57
+
58
+void GroupsModule::onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) {
59
+  leave_all_groups(sess->getLocalTag());
60
+}
61
+
62
+void GroupsModule::leave_all_groups(const string& ltag) {
63
+  GroupsModule::groups_mut.lock();
64
+
65
+  GroupMap::iterator it = GroupsModule::groups_rev.find(ltag);
66
+  if (it != GroupsModule::groups_rev.end()) {
67
+    set<string>& active_groups = it->second;
68
+    for (set<string>::iterator ag_it =
69
+	   active_groups.begin(); ag_it != active_groups.end(); ag_it++) {
70
+      GroupsModule::groups[*ag_it].erase(ltag);
71
+      if (GroupsModule::groups[*ag_it].empty()) {
72
+	DBG("clearing empty group '%s'\n", ag_it->c_str());
73
+	GroupsModule::groups.erase(*ag_it);
74
+      }
75
+    }
76
+    GroupsModule::groups_rev.erase(it);
77
+  }
78
+
79
+  GroupsModule::groups_mut.unlock();
80
+}
81
+
82
+EXEC_ACTION_START(GroupsJoinAction) {
83
+  string groupname = resolveVars(arg, sess, sc_sess, event_params);
84
+  DBG("call '%s' joining group '%s'\n",
85
+      sess->getLocalTag().c_str(), groupname.c_str());
86
+
87
+  GroupsModule::groups_mut.lock();
88
+  GroupsModule::groups[groupname].insert(sess->getLocalTag());
89
+  GroupsModule::groups_rev[sess->getLocalTag()].insert(groupname);
90
+  GroupsModule::groups_mut.unlock();
91
+} EXEC_ACTION_END;
92
+
93
+EXEC_ACTION_START(GroupsLeaveAction) {
94
+  string groupname = resolveVars(arg, sess, sc_sess, event_params);
95
+  string ltag = sess->getLocalTag();
96
+  DBG("call '%s' leaving group '%s'\n",
97
+      ltag.c_str(), groupname.c_str());
98
+
99
+  GroupsModule::groups_mut.lock();
100
+
101
+  GroupMap::iterator it = GroupsModule::groups.find(groupname);
102
+  if (it != GroupsModule::groups.end()) {
103
+    it->second.erase(ltag);
104
+    if (it->second.empty()) {
105
+      DBG("clearing empty group '%s'\n", groupname.c_str());
106
+      GroupsModule::groups.erase(it);
107
+    }
108
+  }
109
+
110
+  it = GroupsModule::groups_rev.find(ltag);
111
+  if (it != GroupsModule::groups_rev.end()) {
112
+    it->second.erase(groupname);
113
+    if (it->second.empty()) {
114
+      DBG("call '%s' in no group any more\n", ltag.c_str());
115
+      GroupsModule::groups_rev.erase(it);
116
+    }
117
+  }
118
+  GroupsModule::groups_mut.unlock();
119
+} EXEC_ACTION_END;
120
+
121
+EXEC_ACTION_START(GroupsLeaveAllAction) {
122
+  string ltag = sess->getLocalTag();
123
+  DBG("call '%s' leaving all groups\n", ltag.c_str());
124
+
125
+  GroupsModule::leave_all_groups(ltag);
126
+} EXEC_ACTION_END;
127
+
128
+CONST_ACTION_2P(GroupsPostEventAction, ',', true);
129
+EXEC_ACTION_START(GroupsPostEventAction) {
130
+  string groupname = resolveVars(par1, sess, sc_sess, event_params);
131
+  string var = resolveVars(par2, sess, sc_sess, event_params);
132
+  map<string, string> ev_params;
133
+
134
+  if (!var.empty()) {
135
+    if (var == "var")
136
+      ev_params = sc_sess->var;
137
+    else {
138
+      vector<string> vars = explode(var, ";");
139
+      for (vector<string>::iterator it =
140
+	     vars.begin(); it != vars.end(); it++)
141
+	ev_params[*it] = sc_sess->var[*it];
142
+    }
143
+  }
144
+
145
+
146
+  DBG("posting event to group '%s'\n", groupname.c_str());
147
+  GroupsModule::groups_mut.unlock();
148
+  GroupMap::iterator grp = GroupsModule::groups.find(groupname);
149
+  bool posted = false;
150
+  if (grp != GroupsModule::groups.end()) {
151
+    for (set<string>::iterator it =
152
+	   grp->second.begin(); it != grp->second.end(); it++) {
153
+      if (*it == sess->getLocalTag())
154
+	continue; // don't post to myself
155
+
156
+      DSMEvent* ev = new DSMEvent();
157
+      ev->params = ev_params;
158
+      if (!AmSessionContainer::instance()->postEvent(*it, ev)) {
159
+	DBG("could not post to call '%s'\n", it->c_str());
160
+      } else {
161
+	DBG("posted event to call '%s'\n", it->c_str());
162
+	posted = true;
163
+      }
164
+    }
165
+  }
166
+  GroupsModule::groups_mut.unlock();
167
+
168
+  if (posted) {
169
+    sc_sess->CLR_ERRNO;
170
+  } else {
171
+    sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
172
+    sc_sess->SET_STRERROR("event could not be posted\n");
173
+  }
174
+
175
+} EXEC_ACTION_END;
0 176
new file mode 100644
... ...
@@ -0,0 +1,67 @@
1
+/*
2
+ * Copyright (C) 2010 Stefan Sayer
3
+ * 
4
+ * Development of this module was sponsored by TelTech Systems Inc
5
+ *
6
+ * This file is part of SEMS, a free SIP media server.
7
+ *
8
+ * SEMS is free software; you can redistribute it and/or modify
9
+ * it under the terms of the GNU General Public License as published by
10
+ * the Free Software Foundation; either version 2 of the License, or
11
+ * (at your option) any later version. This program is released under
12
+ * the GPL with the additional exemption that compiling, linking,
13
+ * and/or using OpenSSL is allowed.
14
+ *
15
+ * For a license to use the SEMS software under conditions
16
+ * other than those described here, or to purchase support for this
17
+ * software, please contact iptel.org by e-mail at the following addresses:
18
+ *    info@iptel.org
19
+ *
20
+ * SEMS is distributed in the hope that it will be useful,
21
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
+ * GNU General Public License for more details.
24
+ *
25
+ * You should have received a copy of the GNU General Public License 
26
+ * along with this program; if not, write to the Free Software 
27
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28
+ */
29
+#ifndef _MOD_MYSQL_H
30
+#define _MOD_MYSQL_H
31
+#include "DSMModule.h"
32
+#include "DSMSession.h"
33
+#include "AmThread.h"
34
+
35
+#define MOD_CLS_NAME GroupsModule 
36
+
37
+#include <set>
38
+using std::set;
39
+#include <map>
40
+using std::map;
41
+#include <string>
42
+using std::string;
43
+
44
+typedef map<string, set<string> > GroupMap;
45
+
46
+DECLARE_MODULE_BEGIN(MOD_CLS_NAME);
47
+
48
+static AmMutex groups_mut;
49
+// group name   ltags
50
+
51
+static GroupMap groups;
52
+// ltags         groups
53
+static GroupMap groups_rev;
54
+
55
+static void leave_all_groups(const string& ltag);
56
+void onBeforeDestroy(DSMSession* sc_sess, AmSession* sess);
57
+
58
+DECLARE_MODULE_END;
59
+
60
+DEF_ACTION_1P(GroupsJoinAction);
61
+DEF_ACTION_1P(GroupsLeaveAction);
62
+DEF_ACTION_1P(GroupsLeaveAllAction);
63
+/* DEF_ACTION_1P(GroupsGetAction); */
64
+/* DEF_ACTION_1P(GroupsGetMembersAction); */
65
+DEF_ACTION_2P(GroupsPostEventAction);
66
+
67
+#endif
... ...
@@ -47,6 +47,10 @@ MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
47 47
   DEF_CMD("sys.unlinkArray", SCUnlinkArrayAction);
48 48
   DEF_CMD("sys.tmpnam", SCTmpNamAction);
49 49
   DEF_CMD("sys.popen", SCPopenAction);
50
+
51
+  DEF_CMD("sys.getTimestamp", SCSysGetTimestampAction);
52
+  DEF_CMD("sys.subTimestamp", SCSysSubTimestampAction);
53
+
50 54
 } MOD_ACTIONEXPORT_END;
51 55
 
52 56
 MOD_CONDITIONEXPORT_BEGIN(MOD_CLS_NAME) {
... ...
@@ -258,7 +262,6 @@ EXEC_ACTION_START(SCTmpNamAction) {
258 262
   }
259 263
 } EXEC_ACTION_END;
260 264
 
261
-
262 265
 CONST_ACTION_2P(SCPopenAction, '=', false);
263 266
 EXEC_ACTION_START(SCPopenAction) {
264 267
   string dst_var = par1;
... ...
@@ -300,3 +303,59 @@ EXEC_ACTION_START(SCPopenAction) {
300 303
   DBG("child process returned status %d\n", status);
301 304
 
302 305
 } EXEC_ACTION_END;
306
+
307
+EXEC_ACTION_START(SCSysGetTimestampAction) {
308
+  string varname = resolveVars(arg, sess, sc_sess, event_params);
309
+  struct timeval tv;
310
+  gettimeofday(&tv, NULL);
311
+
312
+  // long unsigned msecs = tv.tv_sec * 1000 + tv.tv_usec / 1000;
313
+
314
+  char ms_buf[40];
315
+  snprintf(ms_buf, 40, "%lu", tv.tv_sec);
316
+  sc_sess->var[varname+".tv_sec"] = ms_buf;
317
+
318
+  snprintf(ms_buf, 40, "%lu", tv.tv_usec);
319
+  sc_sess->var[varname+".tv_usec"] = ms_buf;
320
+
321
+  DBG("got timestamp $%s=%s, $%s=%s, \n",
322
+      (varname+".tv_sec").c_str(), sc_sess->var[varname+".tv_sec"].c_str(),
323
+      (varname+".tv_usec").c_str(), sc_sess->var[varname+".tv_usec"].c_str()
324
+      );
325
+
326
+} EXEC_ACTION_END;
327
+
328
+CONST_ACTION_2P(SCSysSubTimestampAction, ',', false);
329
+EXEC_ACTION_START(SCSysSubTimestampAction) {
330
+  string t1 = resolveVars(par1, sess, sc_sess, event_params);
331
+  string t2 = resolveVars(par2, sess, sc_sess, event_params);
332
+
333
+  struct timeval tv1;
334
+  struct timeval tv2;
335
+
336
+  tv1.tv_sec = atol(sc_sess->var[t1+".tv_sec"].c_str());
337
+  tv1.tv_usec = atol(sc_sess->var[t1+".tv_usec"].c_str());
338
+
339
+  tv2.tv_sec = atol(sc_sess->var[t2+".tv_sec"].c_str());
340
+  tv2.tv_usec = atol(sc_sess->var[t2+".tv_usec"].c_str());
341
+
342
+  struct timeval diff;
343
+  timersub(&tv1,&tv2,&diff);
344
+
345
+  char ms_buf[40];
346
+  snprintf(ms_buf, 40, "%lu", diff.tv_sec);
347
+  sc_sess->var[t1+".tv_sec"] = ms_buf;
348
+
349
+  snprintf(ms_buf, 40, "%lu", diff.tv_usec);
350
+  sc_sess->var[t1+".tv_usec"] = ms_buf;
351
+
352
+  // may be overflowing - use only if timestamps known
353
+  snprintf(ms_buf, 40, "%lu", diff.tv_sec * 1000 + diff.tv_usec / 1000);
354
+  sc_sess->var[t1+".msec"] = ms_buf;
355
+
356
+  DBG("sub $%s = %s,  $%s = %s,  $%s = %s\n",
357
+      (t1+".tv_sec").c_str(), sc_sess->var[t1+".tv_sec"].c_str(),
358
+      (t1+".tv_usec").c_str(), sc_sess->var[t1+".tv_usec"].c_str(),
359
+      (t1+".msec").c_str(), sc_sess->var[t1+".msec"].c_str()
360
+      );
361
+} EXEC_ACTION_END;
... ...
@@ -40,4 +40,7 @@ DEF_ACTION_1P(SCUnlinkAction);
40 40
 DEF_ACTION_2P(SCUnlinkArrayAction);
41 41
 DEF_ACTION_1P(SCTmpNamAction);
42 42
 DEF_ACTION_2P(SCPopenAction);
43
+
44
+DEF_ACTION_1P(SCSysGetTimestampAction);
45
+DEF_ACTION_2P(SCSysSubTimestampAction);
43 46
 #endif
... ...
@@ -229,11 +229,11 @@ EXEC_ACTION_START(SCUSplitStringAction) {
229 229
     p = str.find("\n", last_p);
230 230
     if (p==string::npos) {
231 231
       if (last_p < str.length())
232
-	sc_sess->var[dst_array+"["+int2str(cntr)+"]"] = str.substr(last_p);
232
+	sc_sess->var[dst_array+"["+int2str((unsigned int)cntr)+"]"] = str.substr(last_p);
233 233
       break;
234 234
     }
235 235
     
236
-    sc_sess->var[dst_array+"["+int2str(cntr++)+"]"] = str.substr(last_p, p-last_p);
236
+    sc_sess->var[dst_array+"["+int2str((unsigned int)cntr++)+"]"] = str.substr(last_p, p-last_p);
237 237
 
238 238
     last_p = p+1;    
239 239
   }
... ...
@@ -58,9 +58,8 @@ int b2b_connectFactory::onLoad()
58 58
   if (cfg.getParameter("transparent_ruri")=="true")
59 59
     TransparentDestination = true;
60 60
   
61
-//   user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer");
62
-//   if(!user_timer_fact) {
63
-//     ERROR("could not load user_timer from session_timer plug-in\n");
61
+//   if (!AmSession::timersSupported()) {
62
+//     ERROR("load session_timer plug-in for timers\n");
64 63
 //     return -1;
65 64
 //   }
66 65
 
... ...
@@ -70,25 +69,18 @@ int b2b_connectFactory::onLoad()
70 69
 
71 70
 AmSession* b2b_connectFactory::onInvite(const AmSipRequest& req)
72 71
 {
73
-//   AmDynInvoke* user_timer = user_timer_fact->getInstance();
74
-//   if(!user_timer) {
75
-//     ERROR("could not get a user timer reference\n");
76
-//     throw AmSession::Exception(500,"could not get a user timer reference");
77
-//   }
78
-
79 72
   string app_param = getHeader(req.hdrs, PARAM_HDR, true);
80 73
 
81 74
   if (!app_param.length()) {
82 75
     throw  AmSession::Exception(500, "b2b_connect: parameters not found");
83 76
   }
84 77
 
85
-  return new b2b_connectDialog(); //user_timer);
78
+  return new b2b_connectDialog();
86 79
 }
87 80
 
88 81
 
89
-b2b_connectDialog::b2b_connectDialog() // AmDynInvoke* user_timer)
90
-: //m_user_timer(user_timer),
91
-  AmB2ABCallerSession()
82
+b2b_connectDialog::b2b_connectDialog()
83
+  : AmB2ABCallerSession()
92 84
 
93 85
 {
94 86
   RTPStream()->setPlayoutType(ADAPTIVE_PLAYOUT); 
... ...
@@ -35,7 +35,6 @@ using std::string;
35 35
 
36 36
 class b2b_connectFactory: public AmSessionFactory
37 37
 {
38
-/*   AmDynInvokeFactory* user_timer_fact; */
39 38
 
40 39
  public:
41 40
   b2b_connectFactory(const string& _app_name);
... ...
@@ -58,11 +57,9 @@ class b2b_connectDialog : public AmB2ABCallerSession
58 57
 
59 58
   AmSipRequest invite_req;
60 59
   
61
-/*   AmDynInvoke* m_user_timer; */
62
-
63 60
  public:
64 61
 
65
-  b2b_connectDialog(); //AmDynInvoke* user_timer);
62
+  b2b_connectDialog();
66 63
   ~b2b_connectDialog();
67 64
   
68 65
   void onSessionStart(const AmSipRequest& req);
... ...
@@ -413,24 +413,10 @@ void CallGenDialog::onSessionStart(const AmSipReply& rep) {
413 413
     call_timer+=rand()%call_time_rand;
414 414
 
415 415
   if (call_timer > 0) {
416
-    AmDynInvokeFactory* UserTimer = AmPlugIn::instance()->getFactory4Di("user_timer");
417
-    if(!UserTimer){
416
+    if (!setTimer(CALL_TIMER, call_timer)) {
418 417
       ERROR("could not load user_timer from session_timer plug-in\n");
419 418
       return;
420 419
     }
421
-    AmDynInvoke* user_timer = UserTimer->getInstance();
422
-    if (!user_timer) {
423
-      ERROR("could not get user_timer\n");
424
-      return;
425
-    }
426
-
427
-    DBG("setting call timer to %d seconds\n", call_timer);
428
-    AmArg di_args,ret;
429
-    di_args.push(CALL_TIMER);
430
-    di_args.push(call_timer);
431
-    di_args.push(getLocalTag().c_str());
432
-      
433
-    user_timer->invoke("setTimer",di_args,ret);
434 420
   }
435 421
 }
436 422
 
... ...
@@ -26,7 +26,7 @@ EXPORT_SESSION_FACTORY(MyCCFactory,MOD_NAME);
26 26
  string MyCCFactory::ConnectSuffix;
27 27
 
28 28
 MyCCFactory::MyCCFactory(const string& _app_name)
29
-  : AmSessionFactory(_app_name), user_timer_fact(NULL)
29
+  : AmSessionFactory(_app_name)
30 30
 {
31 31
 }
32 32
 
... ...
@@ -44,9 +44,8 @@ int MyCCFactory::onLoad()
44 44
   EnterNumber         = cfg.getParameter("enter_number", "/tmp/enter_number.wav"); 
45 45
   ConnectSuffix       = cfg.getParameter("connect_suffix", "@127.0.0.1"); 
46 46
 
47
-  user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer");
48
-  if(!user_timer_fact){
49
-    ERROR("could not load user_timer from session_timer plug-in\n");
47
+  if (!AmSession::timersSupported()) {
48
+    ERROR("load session_timer plug-in for timers\n");
50 49
     return -1;
51 50
   }
52 51
   cc_acc_fact = AmPlugIn::instance()->getFactory4Di("cc_acc");
... ...
@@ -60,26 +59,21 @@ int MyCCFactory::onLoad()
60 59
 
61 60
 AmSession* MyCCFactory::onInvite(const AmSipRequest& req)
62 61
 {
63
-    AmDynInvoke* user_timer = user_timer_fact->getInstance();
64
-    if(!user_timer){
65
-	ERROR("could not get a user timer reference\n");
66
-	throw AmSession::Exception(500,"could not get a user timer reference");
67
-    }
68 62
 
69 63
     AmDynInvoke* cc_acc = cc_acc_fact->getInstance();
70
-    if(!user_timer){
64
+    if(!cc_acc){
71 65
 	ERROR("could not get a cc acc reference\n");
72 66
 	throw AmSession::Exception(500,"could not get a cc acc reference");
73 67
     }
74 68
 
75
-    return new MyCCDialog(cc_acc, user_timer);
69
+    return new MyCCDialog(cc_acc);
76 70
 }
77 71
 
78 72
 
79
-MyCCDialog::MyCCDialog(AmDynInvoke* cc_acc, AmDynInvoke* user_timer)
73
+MyCCDialog::MyCCDialog(AmDynInvoke* cc_acc)
80 74
   : playlist(this), 
81 75
     state(CC_Collecting_PIN),
82
-    cc_acc(cc_acc), user_timer(user_timer),
76
+    cc_acc(cc_acc),
83 77
     AmB2BCallerSession()
84 78
     
85 79
 {
... ...
@@ -209,11 +203,7 @@ bool MyCCDialog::onOtherReply(const AmSipReply& reply) {
209 203
 	// detach from media processor (not in RTP path any more)
210 204
 	AmMediaProcessor::instance()->removeSession(this);
211 205
 	// set the call timer
212
-	AmArg di_args,ret;
213
-	di_args.push(TIMERID_CREDIT_TIMEOUT);
214
-	di_args.push(credit); // in seconds
215
-	di_args.push(dlg.local_tag.c_str());
216
-	user_timer->invoke("setTimer", di_args, ret);
206
+	setTimer(TIMERID_CREDIT_TIMEOUT, credit);
217 207
       }
218 208
     } else {
219 209
       DBG("Callee final error with code %d\n",reply.code);
... ...
@@ -10,7 +10,6 @@ using std::string;
10 10
 class MyCCFactory: public AmSessionFactory
11 11
 {
12 12
 
13
-  AmDynInvokeFactory* user_timer_fact;
14 13
   AmDynInvokeFactory* cc_acc_fact;
15 14
 
16 15
 public:
... ...
@@ -49,11 +48,10 @@ class MyCCDialog : public AmB2BCallerSession
49 48
   void stopAccounting();
50 49
   struct timeval acc_start;
51 50
 
52
-  AmDynInvoke* user_timer;
53 51
   AmDynInvoke* cc_acc;
54 52
 
55 53
  public:
56
-    MyCCDialog(AmDynInvoke* cc_acc, AmDynInvoke* user_timer);
54
+    MyCCDialog(AmDynInvoke* cc_acc);
57 55
     ~MyCCDialog();
58 56
 
59 57
     void onSessionStart(const AmSipRequest& req);
... ...
@@ -6,7 +6,7 @@ mISDNNames.cpp
6 6
 mISDNStack.cpp
7 7
 )
8 8
 
9
-ADD_DEFINITIONS(-DGW_VERSION="0.1")
9
+ADD_DEFINITIONS(-DGW_VERSION=\\\"0.1\\\")
10 10
 INCLUDE_DIRECTORIES(${MISDN_INCLUDE_DIR}/mISDNuser)
11 11
 
12 12
 SET(sems_module_name gateway)
... ...
@@ -174,8 +174,7 @@ void PythonScriptThread::on_stop() {
174 174
 }
175 175
 
176 176
 IvrFactory::IvrFactory(const string& _app_name)
177
-  : AmSessionFactory(_app_name),
178
-    user_timer_fact(NULL)
177
+  : AmSessionFactory(_app_name)
179 178
 {
180 179
 }
181 180
 
... ...
@@ -300,14 +299,7 @@ IvrDialog* IvrFactory::newDlg(const string& name)
300 299
 
301 300
   IvrScriptDesc& mod_desc = mod_it->second;
302 301
 
303
-  AmDynInvoke* user_timer = user_timer_fact->getInstance();
304
-  if(!user_timer){
305
-    ERROR("could not get a user timer reference\n");
306
-    throw AmSession::Exception(500,"could not get a user timer reference");
307
-  }
308
-	
309
-
310
-  IvrDialog* dlg = new IvrDialog(user_timer);
302
+  IvrDialog* dlg = new IvrDialog();
311 303
 
312 304
   PyObject* c_dlg = PyCObject_FromVoidPtr(dlg,NULL);
313 305
   PyObject* dlg_inst = PyObject_CallMethod(mod_desc.dlg_class,"__new__","OO",
... ...
@@ -425,10 +417,8 @@ bool IvrFactory::loadScript(const string& path)
425 417
  */
426 418
 int IvrFactory::onLoad()
427 419
 {
428
-  user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer");
429
-  if(!user_timer_fact){
430
-	
431
-    ERROR("could not load user_timer from session_timer plug-in\n");
420
+  if (!AmSession::timersSupported()) {	
421
+    ERROR("load session_timer plug-in (for timers)\n");
432 422
     return -1;
433 423
   }
434 424
 
... ...
@@ -534,6 +524,10 @@ int IvrDialog::transfer(const string& target)
534 524
   return dlg.transfer(target);
535 525
 }
536 526
 
527
+int IvrDialog::refer(const string& target, int expires) {
528
+  return dlg.refer(target, expires);
529
+}
530
+
537 531
 int IvrDialog::drop()
538 532
 {
539 533
   int res = dlg.drop();
... ...
@@ -571,11 +565,10 @@ AmSession* IvrFactory::onInvite(const AmSipRequest& req)
571 565
   return newDlg(req.user);
572 566
 }
573 567
 
574
-IvrDialog::IvrDialog(AmDynInvoke* user_timer)
568
+IvrDialog::IvrDialog()
575 569
   : py_mod(NULL), 
576 570
     py_dlg(NULL),
577
-    playlist(this),
578
-    user_timer(user_timer)
571
+    playlist(this)
579 572
 {
580 573
   set_sip_relay_only(false);
581 574
 }
... ...
@@ -83,7 +83,6 @@ class IvrFactory: public AmSessionFactory
83 83
 
84 84
   map<string,IvrScriptDesc> mod_reg;
85 85
 
86
-  AmDynInvokeFactory* user_timer_fact;
87 86
   static AmSessionEventHandlerFactory* session_timer_f;
88 87
 
89 88
   void init_python_interpreter(const string& script_path);
... ...
@@ -131,16 +130,16 @@ class IvrDialog : public AmB2BCallerSession
131 130
 
132 131
   void createCalleeSession();
133 132
  public:
134
-  AmDynInvoke* user_timer;
135 133
   AmPlaylist playlist;
136 134
 
137
-  IvrDialog(AmDynInvoke* user_timer);
135
+  IvrDialog();
138 136
   ~IvrDialog();
139 137
 
140 138
   // must be called before everything else.
141 139
   void setPyPtrs(PyObject *mod, PyObject *dlg);
142 140
 
143 141
   int transfer(const string& target);
142
+  int refer(const string& target, int expires);
144 143
   int drop();
145 144
     
146 145
   void onInvite(const AmSipRequest& req);
... ...
@@ -411,13 +411,7 @@ static PyObject* IvrDialogBase_setTimer(IvrDialogBase* self, PyObject* args)
411 411
     return NULL;
412 412
   }
413 413
 
414
-  AmArg di_args,ret;
415
-  di_args.push(id);
416
-  di_args.push(interval);
417
-  di_args.push(self->p_dlg->getLocalTag().c_str());
418
-
419
-  self->p_dlg->user_timer->
420
-    invoke("setTimer", di_args, ret);
414
+  self->p_dlg->setTimer(id, interval);
421 415
     
422 416
   Py_INCREF(Py_None);
423 417
   return Py_None;
... ...
@@ -436,12 +430,7 @@ static PyObject* IvrDialogBase_removeTimer(IvrDialogBase* self, PyObject* args)
436 430
     return NULL;
437 431
   }
438 432
 
439
-  AmArg di_args,ret;
440
-  di_args.push(id);
441
-  di_args.push(self->p_dlg->getLocalTag().c_str());
442
-
443
-  self->p_dlg->user_timer->
444
-    invoke("removeTimer",di_args,ret);
433
+  self->p_dlg->removeTimer(id);
445 434
     
446 435
   Py_INCREF(Py_None);
447 436
   return Py_None;
... ...
@@ -452,12 +441,8 @@ static PyObject* IvrDialogBase_removeTimers(IvrDialogBase* self, PyObject* args)
452 441
 {
453 442
   assert(self->p_dlg);
454 443
     
455
-  AmArg di_args,ret;
456
-  di_args.push(self->p_dlg->getLocalTag().c_str());
444
+  self->p_dlg->removeTimers();
457 445
 
458
-  self->p_dlg->user_timer->
459
-    invoke("removeUserTimers",di_args,ret);
460
-    
461 446
   Py_INCREF(Py_None);
462 447
   return Py_None;
463 448
 }
... ...
@@ -495,6 +480,26 @@ IvrDialogBase_redirect(IvrDialogBase *self, PyObject* args)
495 480
     
496 481
 }
497 482
 
483
+static PyObject*
484
+IvrDialogBase_refer(IvrDialogBase *self, PyObject* args)
485
+{
486
+  assert(self->p_dlg);
487
+    
488
+  char* refer_to=0;
489
+  int expires;
490
+  if(!PyArg_ParseTuple(args,"si",&refer_to, &expires))
491
+    return NULL;
492
+    
493
+  if(self->p_dlg->refer(refer_to, expires)){
494
+    ERROR("REFER failed\n");
495
+    return NULL;
496
+  }
497
+    
498
+  Py_INCREF(Py_None);
499
+  return Py_None;
500
+    
501
+}
502
+
498 503
 static PyMethodDef IvrDialogBase_methods[] = {
499 504
     
500 505
 
... ...
@@ -528,6 +533,9 @@ static PyMethodDef IvrDialogBase_methods[] = {
528 533
    "Send a BYE"
529 534
   },
530 535
   {"redirect", (PyCFunction)IvrDialogBase_redirect, METH_VARARGS,
536
+   "Transfers the remote party to some third party."
537
+  },   
538
+  {"refer", (PyCFunction)IvrDialogBase_refer, METH_VARARGS,
531 539
    "Refers the remote party to some third party."
532 540
   },   
533 541
   {"dropSession", (PyCFunction)IvrDialogBase_dropSession, METH_NOARGS,
... ...
@@ -2,6 +2,8 @@
2 2
 # authentication mode:
3 3
 #    XMLRPC : authenticate against XMLRPC server
4 4
 #    REFER  : add pin to REFER sent out to be checked at proxy
5
+#    TRANSFER  : add pin to R-URI, transfer call flow (see Readme.pin_collect.txt)
6
+
5 7
 auth_mode=XMLRPC
6 8
 
7 9
 # XMLRPC url to authenticate against if auth_mode==XMLRPC
... ...
@@ -1,3 +1,4 @@
1
+# -*- coding: utf-8 -*-
1 2
 from log import *
2 3
 from ivr import *
3 4
 
... ...
@@ -101,6 +102,12 @@ class IvrDialog(IvrDialogBase):
101 102
 						self.fail_msg.open(config['fail_msg'],AUDIO_READ)
102 103
 						self.enqueue(self.fail_msg,None)
103 104
 						
105
+				elif config['auth_mode'] == 'REFER':
106
+					self.state = connect
107
+					self.removeTimer(HINT_TIMER)
108
+					self.transfer_cseq = self.dialog.cseq
109
+					self.refer("sip:" + self.dialog.user + "+" + self.keys + "@" + \
110
+						self.dialog.domain, 20)
104 111
 				else:
105 112
 					self.state = connect
106 113
 					self.removeTimer(HINT_TIMER)
... ...
@@ -120,8 +120,7 @@ extern "C" {
120 120
 }
121 121
 
122 122
 PySemsFactory::PySemsFactory(const string& _app_name)
123
-  : AmSessionFactory(_app_name),
124
-    user_timer_fact(NULL)
123
+  : AmSessionFactory(_app_name)
125 124
 {
126 125
 }
127 126
 
... ...
@@ -228,10 +227,9 @@ AmSession* PySemsFactory::newDlg(const string& name)
228 227
 
229 228
   PySemsScriptDesc& mod_desc = mod_it->second;
230 229
 
231
-  AmDynInvoke* user_timer = user_timer_fact->getInstance();
232
-  if(!user_timer){
233
-    ERROR("could not get a user timer reference\n");
234
-    throw AmSession::Exception(500,"could not get a user timer reference");
230
+  if (!AmSession::timersSupported()) {
231
+    ERROR("load session_timer plugin for timers\n");
232
+    throw AmSession::Exception(500,SIP_REPLY_SERVER_INTERNAL_ERROR);
235 233
   }
236 234
 	
237 235
   PyObject* dlg_inst = PyObject_Call(mod_desc.dlg_class,PyTuple_New(0),NULL);
... ...
@@ -402,10 +400,8 @@ bool PySemsFactory::loadScript(const string& path)
402 400
  */
403 401
 int PySemsFactory::onLoad()
404 402
 {
405
-  user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer");
406
-  if(!user_timer_fact){
407
-	
408
-    ERROR("could not load user_timer from session_timer plug-in\n");
403
+  if (!AmSession::timersSupported()) {
404
+    ERROR("load session_timer plug-in (for timers)\n");
409 405
     return -1;
410 406
   }
411 407
 
... ...
@@ -83,8 +83,6 @@ class PySemsFactory: public AmSessionFactory
83 83
 
84 84
   map<string,PySemsScriptDesc> mod_reg;
85 85
 
86
-  AmDynInvokeFactory* user_timer_fact;
87
-
88 86
   void init_python_interpreter(const string& script_path);
89 87
   void set_sys_path(const string& script_path);
90 88
   void import_py_sems_builtins();
... ...
@@ -20,14 +20,7 @@
20 20
 #include "PySemsB2ABDialog.h"
21 21
 #include "PySemsUtils.h"
22 22
 PySemsB2ABDialog::PySemsB2ABDialog()
23
-  : playlist(this),
24
-    user_timer(NULL)
25
-{
26
-}
27
-
28
-PySemsB2ABDialog::PySemsB2ABDialog(AmDynInvoke* user_timer)
29
-  : playlist(this),
30
-    user_timer(user_timer)
23
+  : playlist(this)
31 24
 {
32 25
 }
33 26
 
... ...
@@ -32,11 +32,9 @@ class PySemsB2ABDialog : public AmB2ABCallerSession,
32 32
   public PySemsDialogBase
33 33
 {
34 34
  public:
35
-  AmDynInvoke* user_timer;
36 35
   AmPlaylist playlist;
37 36
 
38 37
   PySemsB2ABDialog();
39
-  PySemsB2ABDialog(AmDynInvoke* user_timer);
40 38
   virtual ~PySemsB2ABDialog();
41 39
 
42 40
   void onSessionStart(const AmSipRequest& req);
... ...
@@ -21,15 +21,7 @@
21 21
 #include "PySemsB2BDialog.h"
22 22
 #include "PySemsUtils.h"
23 23
 PySemsB2BDialog::PySemsB2BDialog()
24
-  : playlist(this),
25
-    user_timer(NULL)
26
-{
27
-  set_sip_relay_only(false);
28
-}
29
-
30
-PySemsB2BDialog::PySemsB2BDialog(AmDynInvoke* user_timer)
31
-  : playlist(this),
32
-    user_timer(user_timer)
24
+  : playlist(this)
33 25
 {
34 26
   set_sip_relay_only(false);
35 27
 }
... ...
@@ -31,11 +31,9 @@ class PySemsB2BDialog : public AmB2BCallerSession,
31 31
   public PySemsDialogBase
32 32
 {
33 33
  public:
34
-  AmDynInvoke* user_timer;
35 34
   AmPlaylist playlist;
36 35
 
37 36
   PySemsB2BDialog();
38
-  PySemsB2BDialog(AmDynInvoke* user_timer);
39 37
   virtual ~PySemsB2BDialog();
40 38
 
41 39
   void onSessionStart(const AmSipRequest& req);
... ...
@@ -22,25 +22,15 @@