Browse code

wip: adds parsed session parameters extracted from the P-App-Param HF.

Raphael Coeffic authored on 25/05/2011 14:32:10
Showing 42 changed files
... ...
@@ -73,7 +73,8 @@ int AnnounceB2BFactory::onLoad()
73 73
   return 0;
74 74
 }
75 75
 
76
-AmSession* AnnounceB2BFactory::onInvite(const AmSipRequest& req, const string& app_name)
76
+AmSession* AnnounceB2BFactory::onInvite(const AmSipRequest& req, const string& app_name,
77
+					const map<string,string>& app_params)
77 78
 {
78 79
   string announce_path = AnnouncePath;
79 80
   string announce_file = announce_path + req.domain
... ...
@@ -44,7 +44,8 @@ public:
44 44
   AnnounceB2BFactory(const string& _app_name);
45 45
 
46 46
   int onLoad();
47
-  AmSession* onInvite(const AmSipRequest& req, const string& app_name);
47
+  AmSession* onInvite(const AmSipRequest& req, const string& app_name,
48
+		      const map<string,string>& app_params);
48 49
 };
49 50
 
50 51
 /** \brief Session logic implementation of A leg in announce_b2b sessions */
... ...
@@ -68,7 +68,8 @@ int AnnounceTransferFactory::onLoad()
68 68
   return 0;
69 69
 }
70 70
 
71
-AmSession* AnnounceTransferFactory::onInvite(const AmSipRequest& req, const string& app_name)
71
+AmSession* AnnounceTransferFactory::onInvite(const AmSipRequest& req, const string& app_name,
72
+					     const map<string,string>& app_params)
72 73
 {
73 74
   string announce_path = AnnouncePath;
74 75
   string announce_file = announce_path + req.domain 
... ...
@@ -44,7 +44,8 @@ public:
44 44
   AnnounceTransferFactory(const string& _app_name);
45 45
 
46 46
   int onLoad();
47
-  AmSession* onInvite(const AmSipRequest& req, const string& app_name);
47
+  AmSession* onInvite(const AmSipRequest& req, const string& app_name,
48
+		      const map<string,string>& app_params);
48 49
 };
49 50
 
50 51
 /** \brief session logic implementation for announce_transfer sessions */
... ...
@@ -92,7 +92,8 @@ string AnnouncementFactory::getAnnounceFile(const AmSipRequest& req) {
92 92
   return announce_file;
93 93
 }
94 94
 
95
-AmSession* AnnouncementFactory::onInvite(const AmSipRequest& req, const string& app_name)
95
+AmSession* AnnouncementFactory::onInvite(const AmSipRequest& req, const string& app_name,
96
+					 const map<string,string>& app_params)
96 97
 {
97 98
   return new AnnouncementDialog(getAnnounceFile(req), NULL);
98 99
 }
... ...
@@ -49,7 +49,8 @@ public:
49 49
   AnnouncementFactory(const string& _app_name);
50 50
 
51 51
   int onLoad();
52
-  AmSession* onInvite(const AmSipRequest& req, const string& app_name);
52
+  AmSession* onInvite(const AmSipRequest& req, const string& app_name,
53
+		      const map<string,string>& app_params);
53 54
   AmSession* onInvite(const AmSipRequest& req, const string& app_name,
54 55
 		      AmArg& session_params);
55 56
 
... ...
@@ -204,7 +204,8 @@ void AnnRecorderFactory::getAppParams(const AmSipRequest& req, map<string, strin
204 204
   params["type"] = typ;
205 205
 }
206 206
 
207
-AmSession* AnnRecorderFactory::onInvite(const AmSipRequest& req, const string& app_name)
207
+AmSession* AnnRecorderFactory::onInvite(const AmSipRequest& req, const string& app_name,
208
+					const map<string,string>& app_params)
208 209
 {
209 210
   map<string, string> params;
210 211
   getAppParams(req, params);
... ...
@@ -74,7 +74,8 @@ public:
74 74
   AnnRecorderFactory(const string& _app_name);
75 75
 
76 76
   int onLoad();
77
-  AmSession* onInvite(const AmSipRequest& req, const string& app_name);
77
+  AmSession* onInvite(const AmSipRequest& req, const string& app_name,
78
+		      const map<string,string>& app_params);
78 79
   AmSession* onInvite(const AmSipRequest& req, const string& app_name,
79 80
 		      AmArg& session_params);
80 81
 
... ...
@@ -125,7 +125,8 @@ int CallBackFactory::onLoad()
125 125
 }
126 126
 
127 127
 // incoming calls 
128
-AmSession* CallBackFactory::onInvite(const AmSipRequest& req, const string& app_name)
128
+AmSession* CallBackFactory::onInvite(const AmSipRequest& req, const string& app_name,
129
+				     const map<string,string>& app_params)
129 130
 {
130 131
   // or req.from -> with display name ? 
131 132
   DBG("received INVITE from '%s'\n", req.from_uri.c_str());
... ...
@@ -72,7 +72,8 @@ public:
72 72
   static PlayoutType m_PlayoutType;
73 73
 
74 74
   CallBackFactory(const string& _app_name);
75
-  AmSession* onInvite(const AmSipRequest&, const string& app_name);
75
+  AmSession* onInvite(const AmSipRequest&, const string& app_name,
76
+		      const map<string,string>& app_params);
76 77
   AmSession* onInvite(const AmSipRequest& req, const string& app_name,
77 78
 		      AmArg& session_params);
78 79
   int onLoad();
... ...
@@ -180,7 +180,8 @@ AmSession* Click2DialFactory::onInvite(const AmSipRequest& req, const string& ap
180 180
 }
181 181
 
182 182
 
183
-AmSession* Click2DialFactory::onInvite(const AmSipRequest& req, const string& app_name)
183
+AmSession* Click2DialFactory::onInvite(const AmSipRequest& req, const string& app_name,
184
+				       const map<string,string>& app_params)
184 185
 {
185 186
   return new C2DCallerDialog(req, getAnnounceFile(req), NULL, NULL);
186 187
 }
... ...
@@ -52,7 +52,8 @@ class Click2DialFactory: public AmSessionFactory
52 52
     Click2DialFactory(const string& _app_name);
53 53
 
54 54
     int onLoad();
55
-    AmSession* onInvite(const AmSipRequest& req, const string& app_name);
55
+    AmSession* onInvite(const AmSipRequest& req, const string& app_name,
56
+			const map<string,string>& app_params);
56 57
     AmSession* onInvite(const AmSipRequest& req, const string& app_name, AmArg& session_params);
57 58
 };
58 59
 
... ...
@@ -308,7 +308,8 @@ int ConferenceFactory::onLoad()
308 308
   return 0;
309 309
 }
310 310
 
311
-AmSession* ConferenceFactory::onInvite(const AmSipRequest& req, const string& app_name)
311
+AmSession* ConferenceFactory::onInvite(const AmSipRequest& req, const string& app_name,
312
+				       const map<string,string>& app_params)
312 313
 {
313 314
   if ((ConferenceFactory::MaxParticipants > 0) &&
314 315
       (AmConferenceStatus::getConferenceSize(req.user) >=
... ...
@@ -93,7 +93,8 @@ public:
93 93
 #endif
94 94
 
95 95
   ConferenceFactory(const string& _app_name);
96
-  virtual AmSession* onInvite(const AmSipRequest&, const string& app_name);
96
+  virtual AmSession* onInvite(const AmSipRequest&, const string& app_name,
97
+			      const map<string,string>& app_params);
97 98
   virtual AmSession* onRefer(const AmSipRequest& req, const string& app_name);
98 99
   virtual int onLoad();
99 100
 };
... ...
@@ -683,7 +683,8 @@ void DSMFactory::runMonitorAppSelect(const AmSipRequest& req, string& start_diag
683 683
 #undef FALLBACK_OR_EXCEPTION
684 684
 }
685 685
  
686
-AmSession* DSMFactory::onInvite(const AmSipRequest& req, const string& app_name)
686
+AmSession* DSMFactory::onInvite(const AmSipRequest& req, const string& app_name,
687
+				const map<string,string>& app_params)
687 688
 {
688 689
   string start_diag;
689 690
   map<string, string> vars;
... ...
@@ -136,7 +136,8 @@ public:
136 136
 
137 137
 
138 138
   int onLoad();
139
-  AmSession* onInvite(const AmSipRequest& req, const string& app_name);
139
+  AmSession* onInvite(const AmSipRequest& req, const string& app_name,
140
+		      const map<string,string>& app_params);
140 141
   AmSession* onInvite(const AmSipRequest& req, const string& app_name,
141 142
 		      AmArg& session_params);
142 143
   // DI
... ...
@@ -277,7 +277,8 @@ void EarlyAnnounceDialog::onInvite(const AmSipRequest& req)
277 277
 }
278 278
 
279 279
 
280
-AmSession* EarlyAnnounceFactory::onInvite(const AmSipRequest& req, const string& app_name)
280
+AmSession* EarlyAnnounceFactory::onInvite(const AmSipRequest& req, const string& app_name,
281
+					  const map<string,string>& app_params)
281 282
 {
282 283
 
283 284
 #ifdef USE_MYSQL
... ...
@@ -61,7 +61,8 @@ public:
61 61
   EarlyAnnounceFactory(const string& _app_name);
62 62
 
63 63
   int onLoad();
64
-  AmSession* onInvite(const AmSipRequest& req, const string& app_name);
64
+  AmSession* onInvite(const AmSipRequest& req, const string& app_name,
65
+		      const map<string,string>& app_params);
65 66
 };
66 67
 
67 68
 /** \brief session logic implementation for early_announce sessions */
... ...
@@ -105,28 +105,6 @@ extern "C" {
105 105
     return Py_None;
106 106
   }
107 107
 
108
-  static PyObject* ivr_getSessionParam(PyObject*, PyObject* args)
109
-  {
110
-    char* headers;
111
-    char* header_name;
112
-    if(!PyArg_ParseTuple(args,"ss",&headers,&header_name))
113
-      return NULL;
114
-
115
-    string res;
116
-    string iptel_app_param = getHeader(headers, PARAM_HDR, true);
117
-    if (iptel_app_param.length()) {
118
-      res = get_header_keyvalue(iptel_app_param,header_name);
119
-    } else {
120
-      INFO("Use of P-%s is deprecated. \n", header_name);
121
-      INFO("Use '%s: %s=<addr>' instead.\n", PARAM_HDR, header_name);
122
-
123
-      res = getHeader(headers,string("P-") + header_name, true);
124
-    }
125
-
126
-	 
127
-    return PyString_FromString(res.c_str());
128
-  }
129
-
130 108
   static PyObject* ivr_createThread(PyObject*, PyObject* args)
131 109
   {
132 110
     PyObject* py_thread_object = NULL;
... ...
@@ -155,7 +133,6 @@ extern "C" {
155 133
   static PyMethodDef ivr_methods[] = {
156 134
     {"log", (PyCFunction)ivr_log, METH_VARARGS,"Log a message using Sems' logging system"},
157 135
     {"getHeader", (PyCFunction)ivr_getHeader, METH_VARARGS,"Python getHeader wrapper"},
158
-    {"getSessionParam", (PyCFunction)ivr_getSessionParam, METH_VARARGS,"Python getSessionParam wrapper"},
159 136
     {"createThread", (PyCFunction)ivr_createThread, METH_VARARGS, "Create another interpreter thread"},
160 137
     {"setIgnoreSigchld", (PyCFunction)ivr_ignoreSigchld, METH_VARARGS, "ignore SIGCHLD signal"},
161 138
     {NULL}  /* Sentinel */
... ...
@@ -561,10 +538,11 @@ void IvrFactory::setupSessionTimer(AmSession* s) {
561 538
 }
562 539
 
563 540
 /**
564
- * Load a script using user name from URI.
541
+ * Load a script using the app_name.
565 542
  * Note: there is no default script.
566 543
  */
567
-AmSession* IvrFactory::onInvite(const AmSipRequest& req, const string& app_name)
544
+AmSession* IvrFactory::onInvite(const AmSipRequest& req, const string& app_name,
545
+				const map<string,string>& app_params)
568 546
 {
569 547
   return newDlg(app_name);
570 548
 }
... ...
@@ -108,7 +108,8 @@ class IvrFactory: public AmSessionFactory
108 108
   IvrFactory(const string& _app_name);
109 109
 
110 110
   int onLoad();
111
-  AmSession* onInvite(const AmSipRequest& req, const string& app_name);
111
+  AmSession* onInvite(const AmSipRequest& req, const string& app_name,
112
+		      const map<string,string>& app_params);
112 113
 
113 114
   void addDeferredThread(PyObject* pyCallable);
114 115
 
... ...
@@ -94,73 +94,6 @@ static PyObject* IvrDialogBase_onRtpTimeout(IvrDialogBase* self, PyObject*)
94 94
   return Py_None;
95 95
 }
96 96
 
97
-// static PyObject* IvrDialogBase_onSessionStart(IvrDialogBase* self, PyObject*)
98
-// {
99
-//     DBG("no script implementation for onSessionStart(self,hdrs) !!!\n");
100
-
101
-//     PyErr_SetNone(PyExc_NotImplementedError);
102
-//     return NULL; // no return value
103
-// }
104
-
105
-// static PyObject* IvrDialogBase_onBye(IvrDialogBase* self, PyObject*)
106
-// {
107
-//     DBG("no script implementation for onBye(self) !!!\n");
108
-
109
-//     PyErr_SetNone(PyExc_NotImplementedError);
110
-//     return NULL; // no return value
111
-// }
112
-
113
-// static PyObject* IvrDialogBase_onEmptyQueue(IvrDialogBase* self, PyObject*)
114
-// {
115
-//     DBG("no script implementation for onEmptyQueue(self) !!!\n");
116
-
117
-//     PyErr_SetNone(PyExc_NotImplementedError);
118
-//     return NULL; // no return value
119
-// }
120
-
121
-// static PyObject* IvrDialogBase_onDtmf(IvrDialogBase* self, PyObject* args)
122
-// {
123
-//     int key, duration;
124
-//     if(!PyArg_ParseTuple(args,"ii",&key,&duration))
125
-// 	return NULL;
126
-
127
-//     DBG("IvrDialogBase_onDtmf(%i,%i)\n",key,duration);
128
-
129
-//     Py_INCREF(Py_None);
130
-//     return Py_None;
131
-// }
132
-
133
-// static PyObject* IvrDialogBase_onTimer(IvrDialogBase* self, PyObject* args)
134
-// {
135
-//     DBG("IvrDialog::onTimer: no script implementation!!!\n");
136
-
137
-//     PyErr_SetNone(PyExc_NotImplementedError);
138
-//     return NULL; // no return value
139
-// }
140
-
141
-// static PyObject* IvrDialogBase_onOtherBye(IvrDialogBase* self, PyObject*)
142
-// {
143
-//     DBG("IvrDialogBase_onOtherBye()\n");
144
-
145
-//     Py_INCREF(Py_None);
146
-//     return Py_None;
147
-// }
148
-
149
-// static PyObject* IvrDialogBase_onOtherReply(IvrDialogBase* self, PyObject* args)
150
-// {
151
-//     DBG("IvrDialogBase_onOtherReply()\n");
152
-
153
-//     int code;
154
-//     char* reason;
155
-
156
-//     if(!PyArg_ParseTuple(args,"is",&code,&reason))
157
-// 	return NULL;
158
-    
159
-
160
-//     Py_INCREF(Py_None);
161
-//     return Py_None;
162
-// }
163
-
164 97
 //
165 98
 // Call control
166 99
 //
... ...
@@ -500,6 +433,18 @@ IvrDialogBase_refer(IvrDialogBase *self, PyObject* args)
500 433
     
501 434
 }
502 435
 
436
+static PyObject* 
437
+IvrDialogBase_getAppParam(IvrDialogBase *self, PyObject* args)
438
+{
439
+  const char* param_name;
440
+  if(!PyArg_ParseTuple(args,"s",&param_name))
441
+    return NULL;
442
+
443
+  string app_param = self->p_dlg->getAppParam(param_name);
444
+  return PyString_FromString(app_param.c_str());
445
+}
446
+
447
+
503 448
 static PyMethodDef IvrDialogBase_methods[] = {
504 449
     
505 450
 
... ...
@@ -598,6 +543,10 @@ static PyMethodDef IvrDialogBase_methods[] = {
598 543
   {"removeTimers", (PyCFunction)IvrDialogBase_removeTimers, METH_NOARGS,
599 544
    "remove all timers"
600 545
   },    
546
+  // App params
547
+  {"getAppParam", (PyCFunction)IvrDialogBase_getAppParam, METH_VARARGS,
548
+   "retrieves an application parameter"
549
+  },
601 550
 
602 551
   {NULL}  /* Sentinel */
603 552
 };
... ...
@@ -53,7 +53,8 @@ int PrecodedFactory::onLoad()
53 53
     return 0;
54 54
 }
55 55
 
56
-AmSession* PrecodedFactory::onInvite(const AmSipRequest& req, const string& app_name)
56
+AmSession* PrecodedFactory::onInvite(const AmSipRequest& req, const string& app_name,
57
+				     const map<string,string>& app_params)
57 58
 {
58 59
     return new PrecodedDialog(&precoded_file);
59 60
 }
... ...
@@ -42,7 +42,8 @@ public:
42 42
     PrecodedFactory(const string& _app_name);
43 43
 
44 44
     int onLoad();
45
-    AmSession* onInvite(const AmSipRequest& req, const string& app_name);
45
+    AmSession* onInvite(const AmSipRequest& req, const string& app_name,
46
+			const map<string,string>& app_params);
46 47
 };
47 48
 
48 49
 class PrecodedDialog : public AmSession
... ...
@@ -109,7 +109,8 @@ void RegistrationAgentFactory::postEvent(AmEvent* ev) {
109 109
   dialer.postEvent(ev);
110 110
 }
111 111
 
112
-AmSession* RegistrationAgentFactory::onInvite(const AmSipRequest& req, const string& app_name)
112
+AmSession* RegistrationAgentFactory::onInvite(const AmSipRequest& req, const string& app_name,
113
+					      const map<string,string>& app_params)
113 114
 {
114 115
   return NULL;
115 116
 }
... ...
@@ -70,7 +70,8 @@ class RegistrationAgentFactory: public AmSessionFactory
70 70
   RegistrationAgentFactory(const string& _app_name);
71 71
 	
72 72
   int onLoad();
73
-  AmSession* onInvite(const AmSipRequest& req, const string& app_name);
73
+  AmSession* onInvite(const AmSipRequest& req, const string& app_name,
74
+		      const map<string,string>& app_params);
74 75
   void postEvent(AmEvent* ev);
75 76
 };
76 77
 
... ...
@@ -164,7 +164,8 @@ string SBCFactory::getActiveProfileMatch(string& profile_rule, const AmSipReques
164 164
   return res;
165 165
 }
166 166
 
167
-AmSession* SBCFactory::onInvite(const AmSipRequest& req, const string& app_name)
167
+AmSession* SBCFactory::onInvite(const AmSipRequest& req, const string& app_name,
168
+				const map<string,string>& app_params)
168 169
 {
169 170
   AmUriParser ruri_parser, from_parser, to_parser;
170 171
 
... ...
@@ -72,7 +72,8 @@ class SBCFactory: public AmSessionFactory,
72 72
   ~SBCFactory();
73 73
 
74 74
   int onLoad();
75
-  AmSession* onInvite(const AmSipRequest& req, const string& app_name);
75
+  AmSession* onInvite(const AmSipRequest& req, const string& app_name,
76
+		      const map<string,string>& app_params);
76 77
 
77 78
   static AmConfigReader cfg;
78 79
   static AmSessionEventHandlerFactory* session_timer_fact;
... ...
@@ -289,7 +289,8 @@ int VoiceboxFactory::onLoad()
289 289
 }
290 290
 
291 291
 // incoming calls 
292
-AmSession* VoiceboxFactory::onInvite(const AmSipRequest& req, const string& app_name)
292
+AmSession* VoiceboxFactory::onInvite(const AmSipRequest& req, const string& app_name,
293
+				     const map<string,string>& app_params)
293 294
 {
294 295
   string user;
295 296
   string pin;
... ...
@@ -68,7 +68,8 @@ public:
68 68
 
69 69
   VoiceboxFactory(const string& _app_name);
70 70
 
71
-  AmSession* onInvite(const AmSipRequest&, const string& app_name);
71
+  AmSession* onInvite(const AmSipRequest&, const string& app_name,
72
+		      const map<string,string>& app_params);
72 73
 //   AmSession* onInvite(const AmSipRequest& req,
73 74
 // 		      AmArg& session_params);
74 75
   int onLoad();
... ...
@@ -498,7 +498,8 @@ int AnswerMachineFactory::onLoad()
498 498
   return 0;
499 499
 }
500 500
 
501
-AmSession* AnswerMachineFactory::onInvite(const AmSipRequest& req, const string& app_name)
501
+AmSession* AnswerMachineFactory::onInvite(const AmSipRequest& req, const string& app_name,
502
+					  const map<string,string>& app_params)
502 503
 {
503 504
   string language;
504 505
   string email;
... ...
@@ -100,7 +100,8 @@ public:
100 100
   AnswerMachineFactory(const string& _app_name);
101 101
 
102 102
   int onLoad();
103
-  AmSession* onInvite(const AmSipRequest& req, const string& app_name);
103
+  AmSession* onInvite(const AmSipRequest& req, const string& app_name,
104
+		      const map<string,string>& app_params);
104 105
 };
105 106
 
106 107
 class AnswerMachineDialog : public AmSession
... ...
@@ -353,7 +353,8 @@ void WebConferenceFactory::setupSessionTimer(AmSession* s) {
353 353
 }
354 354
 
355 355
 // incoming calls 
356
-AmSession* WebConferenceFactory::onInvite(const AmSipRequest& req, const string& app_name)
356
+AmSession* WebConferenceFactory::onInvite(const AmSipRequest& req, const string& app_name,
357
+					  const map<string,string>& app_params)
357 358
 {
358 359
   if (NULL != session_timer_f) {
359 360
     if (!session_timer_f->onInvite(req, cfg))
... ...
@@ -145,7 +145,8 @@ public:
145 145
 
146 146
 
147 147
   WebConferenceFactory(const string& _app_name);
148
-  AmSession* onInvite(const AmSipRequest&, const string& app_name);
148
+  AmSession* onInvite(const AmSipRequest&, const string& app_name,
149
+		      const map<string,string>& app_params);
149 150
   AmSession* onInvite(const AmSipRequest& req, const string& app_name,
150 151
 		      AmArg& session_params);
151 152
   int onLoad();
... ...
@@ -51,10 +51,11 @@ AmSessionFactory::AmSessionFactory(const string& name)
51 51
 AmSession* AmSessionFactory::onInvite(const AmSipRequest& req, const string& app_name,
52 52
 				      AmArg& session_params) {
53 53
   WARN(" discarding session parameters to new session.\n");
54
-  return onInvite(req,app_name);
54
+  map<string,string> app_params;
55
+  return onInvite(req,app_name,app_params);
55 56
 }
56 57
 
57
-AmSession* AmSessionFactory::onRefer(const AmSipRequest& req, const string& app_name)
58
+AmSession* AmSessionFactory::onRefer(const AmSipRequest& req, const string& app_name, const map<string,string>& app_params)
58 59
 {
59 60
   throw AmSession::Exception(488,"Not accepted here");
60 61
 }
... ...
@@ -63,7 +64,8 @@ AmSession* AmSessionFactory::onRefer(const AmSipRequest& req, const string& app_
63 64
 				     AmArg& session_params)
64 65
 {
65 66
   WARN(" discarding session parameters to new session.\n");
66
-  return onRefer(req,app_name);
67
+  map<string,string> app_params;
68
+  return onRefer(req,app_name,app_params);
67 69
 }
68 70
 
69 71
 int AmSessionFactory::configureModule(AmConfigReader& cfg) {
... ...
@@ -136,18 +136,19 @@ class AmSessionFactory: public AmPluginFactory
136 136
   AmSessionFactory(const string& name);
137 137
 
138 138
   /**
139
-   * Creates a dialog state on new request.
139
+   * Creates a dialog state on new UAS request.
140 140
    * @return 0 if the request is not acceptable.
141 141
    *
142 142
    * Warning:
143 143
    *   This method should not make any expensive
144 144
    *   processing as it would block the server.
145 145
    */
146
-  virtual AmSession* onInvite(const AmSipRequest& req, const string& app_name)=0;
146
+  virtual AmSession* onInvite(const AmSipRequest& req, const string& app_name,
147
+			      const map<string,string>& app_params)=0;
147 148
 
148 149
   /**
149
-   * Creates a dialog state on new request. Passes with 
150
-   * parameters to the new session.
150
+   * Creates a dialog state on new UAC request. 
151
+   * @param session_params parameters passed to the new session by the caller.
151 152
    * 
152 153
    * @return 0 if the request is not acceptable.
153 154
    *
... ...
@@ -166,7 +167,8 @@ class AmSessionFactory: public AmPluginFactory
166 167
    *   This method should not make any expensive
167 168
    *   processing as it would block the server.
168 169
    */
169
-  virtual AmSession* onRefer(const AmSipRequest& req, const string& app_name);
170
+  virtual AmSession* onRefer(const AmSipRequest& req, const string& app_name,
171
+			     const map<string,string>& app_params);
170 172
 
171 173
   /**
172 174
    * Creates a dialog state on new REFER with local-tag.
... ...
@@ -492,6 +492,16 @@ void AmSession::setStopped(bool wakeup) {
492 492
 					      new AmEvent(0));
493 493
 }
494 494
 
495
+string AmSession::getAppParam(const string& param_name) const
496
+{
497
+  map<string,string>::const_iterator param_it;
498
+  param_it = app_params.find(param_name);
499
+  if(param_it != app_params.end())
500
+    return param_it->second;
501
+  else
502
+    return "";
503
+}
504
+
495 505
 void AmSession::destroy() {
496 506
   DBG("AmSession::destroy()\n");
497 507
   AmSessionContainer::instance()->destroySession(this);
... ...
@@ -160,6 +160,13 @@ private:
160 160
   AmDynInvoke* user_timer_ref;
161 161
   
162 162
   void getUserTimerInstance();
163
+
164
+  /** Application parameters passed through P-App-Param HF */
165
+  map<string,string> app_params;
166
+
167
+  /** Sets the application parameters from the original request */
168
+  void setAppParams(const AmSipRequest& req);
169
+
163 170
 protected:
164 171
 
165 172
   /** this is the group the media is processed with 
... ...
@@ -172,6 +179,7 @@ protected:
172 179
   /** Local IP interface to be used for RTP streams */
173 180
   int rtp_interface;
174 181
 
182
+  /** Session event handlers (ex: session timer, UAC auth, etc...) */
175 183
   vector<AmSessionEventHandler*> ev_handlers;
176 184
 
177 185
 public:
... ...
@@ -396,6 +404,12 @@ public:
396 404
   virtual void updateUACTransCSeq(unsigned int old_cseq, unsigned int new_cseq) { }
397 405
 
398 406
   /* ----         Householding                              ---- */
407
+
408
+  /**
409
+   * Get a session parameter ('P-App-Param' HF, etc...)
410
+   */
411
+  string getAppParam(const string& param_name) const;
412
+
399 413
   /**
400 414
    * Destroy the session.
401 415
    * It causes the session to be erased from the active session list
... ...
@@ -419,17 +419,22 @@ AmSession* AmSessionContainer::createSession(const AmSipRequest& req,
419 419
       return NULL;
420 420
   }
421 421
 
422
+  map<string,string> app_params;
423
+  parse_app_params(req.hdrs,app_params);
424
+
422 425
   AmSession* session = NULL;
423 426
   if (req.method == "INVITE") {
424
-    if (NULL != session_params) 
427
+    if (NULL != session_params) {
425 428
       session = session_factory->onInvite(req, app_name, *session_params);
426
-    else 
427
-      session = session_factory->onInvite(req, app_name);
429
+    }
430
+    else {
431
+      session = session_factory->onInvite(req, app_name, app_params);
432
+    }
428 433
   } else if (req.method == "REFER") {
429 434
     if (NULL != session_params) 
430 435
       session = session_factory->onRefer(req, app_name, *session_params);
431 436
     else 
432
-      session = session_factory->onRefer(req, app_name);
437
+      session = session_factory->onRefer(req, app_name, app_params);
433 438
   }
434 439
 
435 440
   if(!session) {
... ...
@@ -442,6 +447,10 @@ AmSession* AmSessionContainer::createSession(const AmSipRequest& req,
442 447
 
443 448
     DBG("onInvite/onRefer returned NULL\n");
444 449
   }
450
+  else {
451
+    // save session parameters
452
+    session->app_params = app_params;
453
+  }
445 454
 
446 455
   return session;
447 456
 }
... ...
@@ -921,6 +921,18 @@ string get_session_param(const string& hdrs, const string& name) {
921 921
   return get_header_keyvalue(iptel_app_param, name);
922 922
 }
923 923
 
924
+void parse_app_params(const string& hdrs, map<string,string>& app_params)
925
+{
926
+  // TODO: use real parser with quoting and optimize
927
+  vector<string> items = explode(getHeader(hdrs, PARAM_HDR, true), ";");
928
+  for (vector<string>::iterator it=items.begin(); 
929
+       it != items.end(); it++) {
930
+    vector<string> kv = explode(*it, "=");
931
+    if (kv.size()==2) 
932
+      app_params.insert(make_pair(kv[0], kv[1]));
933
+  }
934
+}
935
+
924 936
 
925 937
 // support for thread-safe pseudo-random numbers
926 938
 static unsigned int _s_rand=0;
... ...
@@ -40,6 +40,7 @@ using std::string;
40 40
 
41 41
 #include <vector>
42 42
 #include <utility>
43
+#include <map>
43 44
 
44 45
 //#define FIFO_PERM S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH
45 46
 
... ...
@@ -234,6 +235,9 @@ string get_header_keyvalue(const string& param_hdr, const string& short_name, co
234 235
 /** get the value of key @param name from P-Iptel-Param header in hdrs */
235 236
 string get_session_param(const string& hdrs, const string& name);
236 237
 
238
+/** parse the P-App-Param header and extracts the parameters into a map */
239
+void parse_app_params(const string& hdrs, std::map<string,string>& app_params);
240
+
237 241
 /** support for thread-safe pseudo-random numbers  - init function */
238 242
 void init_random();
239 243
 /** support for thread-safe pseudo-random numbers  - make a random number function */
... ...
@@ -72,7 +72,8 @@ int EchoFactory::onLoad()
72 72
   return 0;
73 73
 }
74 74
 
75
-AmSession* EchoFactory::onInvite(const AmSipRequest& req, const string& app_name)
75
+AmSession* EchoFactory::onInvite(const AmSipRequest& req, const string& app_name,
76
+				 const map<string,string>& app_params)
76 77
 {
77 78
   if (NULL != session_timer_f) {
78 79
     if (!session_timer_f->onInvite(req, conf))
... ...
@@ -41,7 +41,8 @@ class EchoFactory: public AmSessionFactory
41 41
 public:
42 42
   EchoFactory(const string& _app_name);
43 43
   virtual int onLoad();
44
-  virtual AmSession* onInvite(const AmSipRequest& req, const string& app_name);
44
+  virtual AmSession* onInvite(const AmSipRequest& req, const string& app_name,
45
+			      const map<string,string>& app_params);
45 46
 };
46 47
 
47 48
 /** \brief echo session logic implementation */