- forward in dialog messages using RMS bridge in B2BUA manner
- move all code related to rms_session_info to dedicated source file
- session_list refactoring to always include all dialog information
needed
- suspend transaction to have non blocking bridging
- random rtp port
- stop using shared memory for MS2 and oRTP, manage all the allocation
from one dedicated process
57 | 56 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,38 @@ |
1 |
+ |
|
2 |
+ |
|
3 |
+ |
|
4 |
+|rms_bridge_f| >> create a_leg and b_leg |
|
5 |
+ >> link them and add them to the sessions |
|
6 |
+ >> suspend a_leg connection |
|
7 |
+ --------------------------- |
|
8 |
+ | caller-leg | callee-leg | |
|
9 |
+ --------------------------- |
|
10 |
+ |offer|answer|offer|answer| |
|
11 |
+ --------------------------- |
|
12 |
+ | x | | x | | // create a resulting offer depending on codecs etc. |
|
13 |
+ --------------------------- |
|
14 |
+ >> BRIDING |
|
15 |
+ |
|
16 |
+|BRIDGING| >> INVITE b_leg using the callee-leg offer's |
|
17 |
+ >> wait for transaction response/timeout |
|
18 |
+ --------------------------- |
|
19 |
+ | caller-leg | callee-leg | |
|
20 |
+ --------------------------- |
|
21 |
+ |offer|answer|offer|answer| |
|
22 |
+ --------------------------- |
|
23 |
+ | x | x | x | x | // create a resulting answer depending on codecs etc. |
|
24 |
+ --------------------------- |
|
25 |
+ >> BRIDGED |
|
26 |
+ |
|
27 |
+|BRIDGED| >> continue a_leg considering the state of b_leg |
|
28 |
+ |
|
29 |
+ |
|
30 |
+ |
|
31 |
+TODO: |
|
32 |
+- Implement and test a_leg received CANCEL handling |
|
33 |
+- Implement and test in-dialog message FAILURE. |
|
34 |
+- Implement RE-INVITE with and without codec modification. |
|
35 |
+- Verify and enforce state control when receiving re-transmission of multiple INITIAL INVITEs / BYEs |
|
36 |
+- The B2BUA logic must be able to handle multiple b_leg Dialogs responses that could be created because of upstream call forking, |
|
37 |
+ when receiving multiple connections https://tools.ietf.org/html/rfc3261#section-15) |
|
38 |
+ a soon as one Dialog connect, we need to terminate / cancel all other Dialogs if any. |
... | ... |
@@ -140,11 +140,7 @@ route { |
140 | 140 |
t_reply("503", "server error"); |
141 | 141 |
} |
142 | 142 |
} |
143 |
- |
|
144 |
- if (is_method("BYE")){ |
|
145 |
- xnotice("BYE RECEIVED [$ci]\n"); |
|
146 |
- rms_media_stop(); |
|
147 |
- } |
|
143 |
+ rms_sip_request(); |
|
148 | 144 |
... |
149 | 145 |
</programlisting></example> |
150 | 146 |
</section> |
... | ... |
@@ -166,12 +162,34 @@ route { |
166 | 162 |
</programlisting></example> |
167 | 163 |
</section> |
168 | 164 |
|
169 |
- <section id="rtp_media_server.f.rms_media_stop"> |
|
170 |
- <title><varname>rms_media_stop</varname> ()</title> |
|
165 |
+ <section id="rtp_media_server.f.rms_session_check"> |
|
166 |
+ <title><varname>rms_session_check</varname> ()</title> |
|
167 |
+ <para> |
|
168 |
+ Returns true if the current SIP message it handled/known by |
|
169 |
+ the RMS module, else it may be handle in any other way by |
|
170 |
+ Kamailio. |
|
171 |
+ </para> |
|
172 |
+ <para> |
|
173 |
+ This function can be used from REQUEST_ROUTE, REPLY_ROUTE and FAILURE_ROUTE. |
|
174 |
+ </para> |
|
175 |
+ <example> |
|
176 |
+ <title>usage example</title> |
|
177 |
+ <programlisting format="linespecific"> |
|
178 |
+... |
|
179 |
+ if (rms_session_check()) { |
|
180 |
+ xnotice("This session is handled by the RMS module\n"); |
|
181 |
+ rms_sip_request(); |
|
182 |
+ } |
|
183 |
+... |
|
184 |
+ </programlisting></example> |
|
185 |
+ </section> |
|
186 |
+ |
|
187 |
+ <section id="rtp_media_server.f.rms_sip_request"> |
|
188 |
+ <title><varname>rms_sip_request</varname> ()</title> |
|
171 | 189 |
<para> |
172 |
- This should be called on reception of a BYE, this will |
|
173 |
- delete the RTP session and the media ressources. |
|
174 |
- and reply "200 OK". |
|
190 |
+ This should be called for every in-dialog SIP request, |
|
191 |
+ it will be forwarded behaving as a B2BUA, the transaction |
|
192 |
+ will be suspended until the second leg replies. |
|
175 | 193 |
</para> |
176 | 194 |
<para> |
177 | 195 |
If the SIP session is not found "481 Call/Transaction Does Not Exist" |
... | ... |
@@ -184,8 +202,8 @@ route { |
184 | 202 |
<title>usage example</title> |
185 | 203 |
<programlisting format="linespecific"> |
186 | 204 |
... |
187 |
- if (is_method("BYE")){ |
|
188 |
- rms_media_stop(); |
|
205 |
+ if (rms_session_check()) { |
|
206 |
+ rms_sip_request(); |
|
189 | 207 |
} |
190 | 208 |
... |
191 | 209 |
</programlisting></example> |
... | ... |
@@ -68,11 +68,11 @@ static MSFactory *rms_create_factory() |
68 | 68 |
|
69 | 69 |
int rms_media_init() |
70 | 70 |
{ |
71 |
- OrtpMemoryFunctions ortp_memory_functions; |
|
72 |
- ortp_memory_functions.malloc_fun = ptr_shm_malloc; |
|
73 |
- ortp_memory_functions.realloc_fun = ptr_shm_realloc; |
|
74 |
- ortp_memory_functions.free_fun = ptr_shm_free; |
|
75 |
- ortp_set_memory_functions(&ortp_memory_functions); |
|
71 |
+ // OrtpMemoryFunctions ortp_memory_functions; |
|
72 |
+ // ortp_memory_functions.malloc_fun = ptr_shm_malloc; |
|
73 |
+ // ortp_memory_functions.realloc_fun = ptr_shm_realloc; |
|
74 |
+ // ortp_memory_functions.free_fun = ptr_shm_free; |
|
75 |
+ // ortp_set_memory_functions(&ortp_memory_functions); |
|
76 | 76 |
ortp_init(); |
77 | 77 |
return 1; |
78 | 78 |
} |
... | ... |
@@ -82,18 +82,17 @@ static MSTicker *rms_create_ticker(char *name) |
82 | 82 |
MSTickerParams params; |
83 | 83 |
params.name = name; |
84 | 84 |
params.prio = MS_TICKER_PRIO_NORMAL; |
85 |
+ LM_DBG("\n"); |
|
85 | 86 |
return ms_ticker_new_with_params(¶ms); |
86 | 87 |
} |
87 | 88 |
|
88 | 89 |
void rms_media_destroy(call_leg_media_t *m) |
89 | 90 |
{ |
90 |
- LM_INFO("rtp_session_destroy[%p]\n", m->rtps); |
|
91 |
+ LM_DBG("rtp_session_destroy[%p]\n", m->rtps); |
|
91 | 92 |
rtp_session_destroy(m->rtps); |
92 | 93 |
m->rtps = NULL; |
93 |
- LM_INFO("ms_ticker[%p]\n", m->ms_ticker); |
|
94 | 94 |
ms_ticker_destroy(m->ms_ticker); |
95 | 95 |
m->ms_ticker = NULL; |
96 |
- LM_INFO("ms_factory_destroy[%p]\n", m->ms_factory); |
|
97 | 96 |
ms_factory_destroy(m->ms_factory); |
98 | 97 |
m->ms_factory = NULL; |
99 | 98 |
} |
... | ... |
@@ -114,7 +113,8 @@ int create_call_leg_media(call_leg_media_t *m) |
114 | 113 |
m->ms_rtprecv = ms_factory_create_filter(m->ms_factory, MS_RTP_RECV_ID); |
115 | 114 |
m->ms_rtpsend = ms_factory_create_filter(m->ms_factory, MS_RTP_SEND_ID); |
116 | 115 |
|
117 |
- LM_INFO("codec[%s]\n", m->pt->mime_type); |
|
116 |
+ LM_INFO("codec[%s] rtprecv[%p] rtpsend[%p]\n", m->pt->mime_type, |
|
117 |
+ m->ms_rtprecv, m->ms_rtpsend); |
|
118 | 118 |
m->ms_encoder = ms_factory_create_encoder(m->ms_factory, m->pt->mime_type); |
119 | 119 |
if(!m->ms_encoder) { |
120 | 120 |
LM_ERR("creating encoder failed.\n"); |
... | ... |
@@ -128,26 +128,6 @@ int create_call_leg_media(call_leg_media_t *m) |
128 | 128 |
return 1; |
129 | 129 |
} |
130 | 130 |
|
131 |
-int rms_bridge(call_leg_media_t *m1, call_leg_media_t *m2) |
|
132 |
-{ |
|
133 |
- MSConnectionHelper h; |
|
134 |
- m1->ms_ticker = rms_create_ticker(NULL); |
|
135 |
- |
|
136 |
- // direction 1 |
|
137 |
- ms_connection_helper_start(&h); |
|
138 |
- ms_connection_helper_link(&h, m1->ms_rtprecv, -1, 0); |
|
139 |
- ms_connection_helper_link(&h, m2->ms_rtpsend, 0, -1); |
|
140 |
- |
|
141 |
- // direction 2 |
|
142 |
- ms_connection_helper_start(&h); |
|
143 |
- ms_connection_helper_link(&h, m2->ms_rtprecv, -1, 0); |
|
144 |
- ms_connection_helper_link(&h, m1->ms_rtpsend, 0, -1); |
|
145 |
- |
|
146 |
- ms_ticker_attach_multiple( |
|
147 |
- m1->ms_ticker, m1->ms_rtprecv, m2->ms_rtprecv, NULL); |
|
148 |
- |
|
149 |
- return 1; |
|
150 |
-} |
|
151 | 131 |
|
152 | 132 |
static void rms_player_eof( |
153 | 133 |
void *user_data, MSFilter *f, unsigned int event, void *event_data) |
... | ... |
@@ -159,54 +139,13 @@ static void rms_player_eof( |
159 | 139 |
MS_UNUSED(f), MS_UNUSED(event_data); |
160 | 140 |
} |
161 | 141 |
|
162 |
-int rms_stop_bridge(call_leg_media_t *m1, call_leg_media_t *m2) |
|
163 |
-{ |
|
164 |
- MSConnectionHelper h; |
|
165 |
- if(!m1->ms_ticker) |
|
166 |
- return -1; |
|
167 |
- if(m1->ms_rtpsend) |
|
168 |
- ms_ticker_detach(m1->ms_ticker, m1->ms_rtpsend); |
|
169 |
- if(m1->ms_rtprecv) |
|
170 |
- ms_ticker_detach(m1->ms_ticker, m1->ms_rtprecv); |
|
171 |
- if(m2->ms_rtpsend) |
|
172 |
- ms_ticker_detach(m1->ms_ticker, m2->ms_rtpsend); |
|
173 |
- if(m2->ms_rtprecv) |
|
174 |
- ms_ticker_detach(m1->ms_ticker, m2->ms_rtprecv); |
|
175 |
- rtp_stats_display(rtp_session_get_stats(m1->rtps), |
|
176 |
- " AUDIO BRIDGE offer RTP STATISTICS "); |
|
177 |
- rtp_stats_display(rtp_session_get_stats(m2->rtps), |
|
178 |
- " AUDIO BRIDGE answer RTP STATISTICS "); |
|
179 |
- ms_factory_log_statistics(m1->ms_factory); |
|
180 | 142 |
|
181 |
- ms_connection_helper_start(&h); |
|
182 |
- if(m1->ms_rtprecv) |
|
183 |
- ms_connection_helper_unlink(&h, m1->ms_rtprecv, -1, 0); |
|
184 |
- if(m2->ms_rtpsend) |
|
185 |
- ms_connection_helper_unlink(&h, m2->ms_rtpsend, 0, -1); |
|
186 |
- |
|
187 |
- ms_connection_helper_start(&h); |
|
188 |
- if(m2->ms_rtprecv) |
|
189 |
- ms_connection_helper_unlink(&h, m2->ms_rtprecv, -1, 0); |
|
190 |
- if(m1->ms_rtpsend) |
|
191 |
- ms_connection_helper_unlink(&h, m1->ms_rtpsend, 0, -1); |
|
192 |
- |
|
193 |
- if(m1->ms_rtpsend) |
|
194 |
- ms_filter_destroy(m1->ms_rtpsend); |
|
195 |
- if(m1->ms_rtprecv) |
|
196 |
- ms_filter_destroy(m1->ms_rtprecv); |
|
197 |
- if(m2->ms_rtpsend) |
|
198 |
- ms_filter_destroy(m2->ms_rtpsend); |
|
199 |
- if(m2->ms_rtprecv) |
|
200 |
- ms_filter_destroy(m2->ms_rtprecv); |
|
201 |
- return 1; |
|
202 |
-} |
|
203 |
- |
|
204 |
- |
|
205 |
-int rms_get_dtmf(call_leg_media_t *m, char dtmf) { |
|
206 |
-// static void tone_detected_cb(void *data, MSFilter *f, unsigned int event_id, MSToneDetectorEvent *ev) { |
|
207 |
-// MS_UNUSED(data), MS_UNUSED(f), MS_UNUSED(event_id), MS_UNUSED(ev); |
|
208 |
-// ms_tester_tone_detected = TRUE; |
|
209 |
-// } |
|
143 |
+int rms_get_dtmf(call_leg_media_t *m, char dtmf) |
|
144 |
+{ |
|
145 |
+ // static void tone_detected_cb(void *data, MSFilter *f, unsigned int event_id, MSToneDetectorEvent *ev) { |
|
146 |
+ // MS_UNUSED(data), MS_UNUSED(f), MS_UNUSED(event_id), MS_UNUSED(ev); |
|
147 |
+ // ms_tester_tone_detected = TRUE; |
|
148 |
+ // } |
|
210 | 149 |
return 1; |
211 | 150 |
} |
212 | 151 |
|
... | ... |
@@ -216,12 +155,17 @@ int rms_playfile(call_leg_media_t *m, rms_action_t *a) |
216 | 155 |
if(!m->ms_player) |
217 | 156 |
return 0; |
218 | 157 |
ms_filter_add_notify_callback(m->ms_player, rms_player_eof, a, TRUE); |
219 |
- ms_filter_call_method(m->ms_player, MS_FILE_PLAYER_OPEN, (void *)a->param.s); |
|
158 |
+ ms_filter_call_method( |
|
159 |
+ m->ms_player, MS_FILE_PLAYER_OPEN, (void *)a->param.s); |
|
220 | 160 |
ms_filter_call_method(m->ms_player, MS_FILE_PLAYER_START, NULL); |
221 |
- ms_filter_call_method(m->ms_player, MS_FILTER_GET_SAMPLE_RATE, &file_sample_rate); |
|
222 |
- ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_SAMPLE_RATE, &file_sample_rate); |
|
223 |
- ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_OUTPUT_SAMPLE_RATE, &m->pt->clock_rate); |
|
224 |
- ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_OUTPUT_NCHANNELS, &m->pt->channels); |
|
161 |
+ ms_filter_call_method( |
|
162 |
+ m->ms_player, MS_FILTER_GET_SAMPLE_RATE, &file_sample_rate); |
|
163 |
+ ms_filter_call_method( |
|
164 |
+ m->ms_resampler, MS_FILTER_SET_SAMPLE_RATE, &file_sample_rate); |
|
165 |
+ ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_OUTPUT_SAMPLE_RATE, |
|
166 |
+ &m->pt->clock_rate); |
|
167 |
+ ms_filter_call_method( |
|
168 |
+ m->ms_resampler, MS_FILTER_SET_OUTPUT_NCHANNELS, &m->pt->channels); |
|
225 | 169 |
LM_INFO("clock[%d][%d]\n", m->pt->clock_rate, file_sample_rate); |
226 | 170 |
return 1; |
227 | 171 |
} |
... | ... |
@@ -232,23 +176,30 @@ int rms_start_media(call_leg_media_t *m, char *file_name) |
232 | 176 |
int channels = 1; |
233 | 177 |
int file_sample_rate = 8000; |
234 | 178 |
m->ms_ticker = rms_create_ticker(NULL); |
235 |
- if(!m->ms_ticker) goto error; |
|
179 |
+ if(!m->ms_ticker) |
|
180 |
+ goto error; |
|
236 | 181 |
m->ms_player = ms_factory_create_filter(m->ms_factory, MS_FILE_PLAYER_ID); |
237 |
- if(!m->ms_player) goto error; |
|
182 |
+ if(!m->ms_player) |
|
183 |
+ goto error; |
|
238 | 184 |
m->ms_resampler = ms_factory_create_filter(m->ms_factory, MS_RESAMPLE_ID); |
239 |
- if(!m->ms_resampler) goto error; |
|
185 |
+ if(!m->ms_resampler) |
|
186 |
+ goto error; |
|
240 | 187 |
// m->ms_recorder = ms_factory_create_filter(m->ms_factory, |
241 | 188 |
// MS_FILE_PLAYER_ID); |
242 | 189 |
m->ms_voidsink = ms_factory_create_filter(m->ms_factory, MS_VOID_SINK_ID); |
243 |
- if(!m->ms_voidsink) goto error; |
|
190 |
+ if(!m->ms_voidsink) |
|
191 |
+ goto error; |
|
244 | 192 |
LM_INFO("m[%p]call-id[%p]\n", m, m->si->callid.s); |
245 | 193 |
|
246 | 194 |
ms_filter_call_method( |
247 | 195 |
m->ms_player, MS_FILTER_SET_OUTPUT_NCHANNELS, &channels); |
248 | 196 |
ms_filter_call_method_noarg(m->ms_player, MS_FILE_PLAYER_START); |
249 |
- ms_filter_call_method(m->ms_player, MS_FILTER_GET_SAMPLE_RATE, &file_sample_rate); |
|
250 |
- ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_SAMPLE_RATE, &file_sample_rate); |
|
251 |
- ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_OUTPUT_SAMPLE_RATE, &m->pt->clock_rate); |
|
197 |
+ ms_filter_call_method( |
|
198 |
+ m->ms_player, MS_FILTER_GET_SAMPLE_RATE, &file_sample_rate); |
|
199 |
+ ms_filter_call_method( |
|
200 |
+ m->ms_resampler, MS_FILTER_SET_SAMPLE_RATE, &file_sample_rate); |
|
201 |
+ ms_filter_call_method(m->ms_resampler, MS_FILTER_SET_OUTPUT_SAMPLE_RATE, |
|
202 |
+ &m->pt->clock_rate); |
|
252 | 203 |
|
253 | 204 |
// sending graph |
254 | 205 |
ms_connection_helper_start(&h); |
... | ... |
@@ -324,3 +275,89 @@ int rms_stop_media(call_leg_media_t *m) |
324 | 275 |
rms_media_destroy(m); |
325 | 276 |
return 1; |
326 | 277 |
} |
278 |
+ |
|
279 |
+int rms_bridge(call_leg_media_t *m1, call_leg_media_t *m2) |
|
280 |
+{ |
|
281 |
+ MSConnectionHelper h; |
|
282 |
+ m1->ms_ticker = rms_create_ticker(NULL); |
|
283 |
+ LM_NOTICE("[%p][%p][%p][%p]\n", m1->ms_rtprecv, m1->ms_rtpsend, |
|
284 |
+ m2->ms_rtprecv, m2->ms_rtpsend); |
|
285 |
+ // direction 1 |
|
286 |
+ ms_connection_helper_start(&h); |
|
287 |
+ ms_connection_helper_link(&h, m1->ms_rtprecv, -1, 0); |
|
288 |
+ ms_connection_helper_link(&h, m2->ms_rtpsend, 0, -1); |
|
289 |
+ |
|
290 |
+ LM_NOTICE("[%p][%p][%p][%p]2\n", m1->ms_rtprecv, m1->ms_rtpsend, |
|
291 |
+ m2->ms_rtprecv, m2->ms_rtpsend); |
|
292 |
+ // direction 2 |
|
293 |
+ ms_connection_helper_start(&h); |
|
294 |
+ ms_connection_helper_link(&h, m2->ms_rtprecv, -1, 0); |
|
295 |
+ ms_connection_helper_link(&h, m1->ms_rtpsend, 0, -1); |
|
296 |
+ |
|
297 |
+ ms_ticker_attach_multiple( |
|
298 |
+ m1->ms_ticker, m1->ms_rtprecv, m2->ms_rtprecv, NULL); |
|
299 |
+ |
|
300 |
+ return 1; |
|
301 |
+} |
|
302 |
+ |
|
303 |
+int rms_stop_bridge(call_leg_media_t *m1, call_leg_media_t *m2) |
|
304 |
+{ |
|
305 |
+ MSConnectionHelper h; |
|
306 |
+ MSTicker *ticker = NULL; |
|
307 |
+ |
|
308 |
+ if(m1->ms_ticker) { |
|
309 |
+ ticker = m1->ms_ticker; |
|
310 |
+ } |
|
311 |
+ if(m2->ms_ticker) { |
|
312 |
+ ticker = m2->ms_ticker; |
|
313 |
+ } |
|
314 |
+ if(!ticker) |
|
315 |
+ return -1; |
|
316 |
+ |
|
317 |
+ if(m1->ms_rtprecv) |
|
318 |
+ ms_ticker_detach(ticker, m1->ms_rtprecv); |
|
319 |
+ if(m1->ms_rtpsend) |
|
320 |
+ ms_ticker_detach(ticker, m1->ms_rtpsend); |
|
321 |
+ if(m2->ms_rtprecv) |
|
322 |
+ ms_ticker_detach(ticker, m2->ms_rtprecv); |
|
323 |
+ if(m2->ms_rtpsend) |
|
324 |
+ ms_ticker_detach(ticker, m2->ms_rtpsend); |
|
325 |
+ |
|
326 |
+ ms_connection_helper_start(&h); |
|
327 |
+ if(m1->ms_rtprecv) |
|
328 |
+ ms_connection_helper_unlink(&h, m1->ms_rtprecv, -1, 0); |
|
329 |
+ if(m2->ms_rtpsend) |
|
330 |
+ ms_connection_helper_unlink(&h, m2->ms_rtpsend, 0, -1); |
|
331 |
+ |
|
332 |
+ ms_connection_helper_start(&h); |
|
333 |
+ if(m2->ms_rtprecv) |
|
334 |
+ ms_connection_helper_unlink(&h, m2->ms_rtprecv, -1, 0); |
|
335 |
+ if(m1->ms_rtpsend) |
|
336 |
+ ms_connection_helper_unlink(&h, m1->ms_rtpsend, 0, -1); |
|
337 |
+ |
|
338 |
+ rtp_stats_display(rtp_session_get_stats(m1->rtps), |
|
339 |
+ " AUDIO BRIDGE offer RTP STATISTICS "); |
|
340 |
+ |
|
341 |
+ rtp_stats_display(rtp_session_get_stats(m2->rtps), |
|
342 |
+ " AUDIO BRIDGE answer RTP STATISTICS "); |
|
343 |
+ |
|
344 |
+ if(m1->ms_rtpsend) |
|
345 |
+ ms_filter_destroy(m1->ms_rtpsend); |
|
346 |
+ if(m1->ms_rtprecv) |
|
347 |
+ ms_filter_destroy(m1->ms_rtprecv); |
|
348 |
+ if(m2->ms_rtpsend) |
|
349 |
+ ms_filter_destroy(m2->ms_rtpsend); |
|
350 |
+ if(m2->ms_rtprecv) |
|
351 |
+ ms_filter_destroy(m2->ms_rtprecv); |
|
352 |
+ |
|
353 |
+ rtp_session_destroy(m1->rtps); |
|
354 |
+ rtp_session_destroy(m2->rtps); |
|
355 |
+ if(m1->ms_ticker) |
|
356 |
+ ms_ticker_destroy(m1->ms_ticker); |
|
357 |
+ if(m2->ms_ticker) |
|
358 |
+ ms_ticker_destroy(m2->ms_ticker); |
|
359 |
+ m1->ms_ticker = NULL; |
|
360 |
+ m2->ms_ticker = NULL; |
|
361 |
+ ms_factory_log_statistics(m1->ms_factory); |
|
362 |
+ return 1; |
|
363 |
+} |
327 | 364 |
old mode 100644 |
328 | 365 |
new mode 100755 |
... | ... |
@@ -34,9 +34,12 @@ |
34 | 34 |
#include <ortp/ortp.h> |
35 | 35 |
#include <ortp/port.h> |
36 | 36 |
|
37 |
-struct rms_session_info; |
|
37 |
+#include "rtp_media_server.h" |
|
38 |
+// #include "rms_session_info.h" |
|
39 |
+// struct rms_session_info; |
|
38 | 40 |
typedef struct rms_action rms_action_t; |
39 | 41 |
|
42 |
+ |
|
40 | 43 |
typedef struct call_leg_media |
41 | 44 |
{ |
42 | 45 |
MSFactory *ms_factory; |
... | ... |
@@ -58,7 +61,7 @@ typedef struct call_leg_media |
58 | 61 |
int local_port; |
59 | 62 |
str remote_ip; |
60 | 63 |
int remote_port; |
61 |
- struct rms_session_info *si; |
|
64 |
+ const struct rms_session_info *si; |
|
62 | 65 |
} call_leg_media_t; |
63 | 66 |
|
64 | 67 |
int create_call_leg_media(call_leg_media_t *m); |
... | ... |
@@ -22,6 +22,7 @@ |
22 | 22 |
#include "rms_util.h" |
23 | 23 |
#include "../../core/data_lump.h" |
24 | 24 |
#include "../../core/parser/parse_content.h" |
25 |
+#include "../../core/parser/sdp/sdp.h" |
|
25 | 26 |
|
26 | 27 |
// https://tools.ietf.org/html/rfc4566 |
27 | 28 |
// (protocol version) |
... | ... |
@@ -37,28 +38,98 @@ const char *sdp_t = "t=0 0\r\n"; |
37 | 38 |
//"a=rtpmap:96 opus/48000/2\r\n" |
38 | 39 |
//"a=fmtp:96 useinbandfec=1\r\n"; |
39 | 40 |
|
40 |
-static char *rms_sdp_get_rtpmap(str body, int type_number) |
|
41 |
+int rms_get_sdp_info(rms_sdp_info_t *sdp_info, struct sip_msg *msg) |
|
41 | 42 |
{ |
42 |
- char *pos = body.s; |
|
43 |
- while((pos = strstr(pos, "a=rtpmap:"))) { |
|
44 |
- int id; |
|
45 |
- int sampling_rate; |
|
46 |
- char codec[64]; |
|
47 |
- sscanf(pos, "a=rtpmap:%d %s/%d", &id, codec, &sampling_rate); |
|
48 |
- if(id == type_number) { |
|
49 |
- LM_INFO("[%d][%s/%d]\n", id, codec, sampling_rate); |
|
50 |
- return rms_char_dup(codec, 1); |
|
43 |
+ sdp_session_cell_t *sdp_session; |
|
44 |
+ sdp_stream_cell_t *sdp_stream; |
|
45 |
+ str media_ip, media_port; |
|
46 |
+ int sdp_session_num = 0; |
|
47 |
+ int sdp_stream_num = get_sdp_stream_num(msg); |
|
48 |
+ if(parse_sdp(msg) < 0) { |
|
49 |
+ LM_INFO("can not parse sdp\n"); |
|
50 |
+ return 0; |
|
51 |
+ } |
|
52 |
+ sdp_info_t *sdp = (sdp_info_t *)msg->body; |
|
53 |
+ if(!sdp) { |
|
54 |
+ LM_INFO("sdp null\n"); |
|
55 |
+ return 0; |
|
56 |
+ } |
|
57 |
+ rms_str_dup(&sdp_info->recv_body, &sdp->text, 1); |
|
58 |
+ if(!sdp_info->recv_body.s) |
|
59 |
+ goto error; |
|
60 |
+ LM_INFO("sdp body - type[%d]\n", sdp->type); |
|
61 |
+ if(sdp_stream_num > 1 || !sdp_stream_num) { |
|
62 |
+ LM_INFO("only support one stream[%d]\n", sdp_stream_num); |
|
63 |
+ } |
|
64 |
+ sdp_stream_num = 0; |
|
65 |
+ sdp_session = get_sdp_session(msg, sdp_session_num); |
|
66 |
+ if(!sdp_session) { |
|
67 |
+ return 0; |
|
68 |
+ } else { |
|
69 |
+ int sdp_stream_num = 0; |
|
70 |
+ sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); |
|
71 |
+ if(!sdp_stream) { |
|
72 |
+ LM_INFO("can not get the sdp stream\n"); |
|
73 |
+ return 0; |
|
74 |
+ } else { |
|
75 |
+ rms_str_dup(&sdp_info->payloads, &sdp_stream->payloads, 1); |
|
76 |
+ if(!sdp_info->payloads.s) |
|
77 |
+ goto error; |
|
51 | 78 |
} |
52 |
- pos++; |
|
53 | 79 |
} |
54 |
- return NULL; |
|
80 |
+ if(sdp_stream->ip_addr.s && sdp_stream->ip_addr.len > 0) { |
|
81 |
+ media_ip = sdp_stream->ip_addr; |
|
82 |
+ } else { |
|
83 |
+ media_ip = sdp_session->ip_addr; |
|
84 |
+ } |
|
85 |
+ rms_str_dup(&sdp_info->remote_ip, &media_ip, 1); |
|
86 |
+ if(!sdp_info->remote_ip.s) |
|
87 |
+ goto error; |
|
88 |
+ rms_str_dup(&media_port, &sdp_stream->port, 0); |
|
89 |
+ if(!media_port.s) |
|
90 |
+ goto error; |
|
91 |
+ sdp_info->remote_port = atoi(media_port.s); |
|
92 |
+ pkg_free(media_port.s); |
|
93 |
+ return 1; |
|
94 |
+error: |
|
95 |
+ rms_sdp_info_free(sdp_info); |
|
96 |
+ return 0; |
|
55 | 97 |
} |
56 | 98 |
|
99 |
+//static char *rms_sdp_get_rtpmap(str body, int type_number) |
|
100 |
+//{ |
|
101 |
+// char *pos = body.s; |
|
102 |
+// while((pos = strstr(pos, "a=rtpmap:"))) { |
|
103 |
+// int id; |
|
104 |
+// int sampling_rate; |
|
105 |
+// char codec[64]; |
|
106 |
+// sscanf(pos, "a=rtpmap:%d %s/%d", &id, codec, &sampling_rate); |
|
107 |
+// if(id == type_number) { |
|
108 |
+// LM_INFO("[%d][%s/%d]\n", id, codec, sampling_rate); |
|
109 |
+// return rms_char_dup(codec, 1); |
|
110 |
+// } |
|
111 |
+// pos++; |
|
112 |
+// } |
|
113 |
+// return NULL; |
|
114 |
+//} |
|
115 |
+ |
|
57 | 116 |
void rms_sdp_info_init(rms_sdp_info_t *sdp_info) |
58 | 117 |
{ |
59 | 118 |
memset(sdp_info, 0, sizeof(rms_sdp_info_t)); |
60 | 119 |
} |
61 | 120 |
|
121 |
+int rms_sdp_info_clone(rms_sdp_info_t *dst, rms_sdp_info_t *src) |
|
122 |
+{ |
|
123 |
+ rms_sdp_info_init(dst); |
|
124 |
+ if(!rms_str_dup(&dst->remote_ip, &src->remote_ip, 1)) |
|
125 |
+ return 0; |
|
126 |
+ if(!rms_str_dup(&dst->payloads, &src->payloads, 1)) |
|
127 |
+ return 0; |
|
128 |
+ if(!rms_str_dup(&dst->new_body, &src->new_body, 1)) |
|
129 |
+ return 0; |
|
130 |
+ return 1; |
|
131 |
+} |
|
132 |
+ |
|
62 | 133 |
void rms_sdp_info_free(rms_sdp_info_t *sdp_info) |
63 | 134 |
{ |
64 | 135 |
if(sdp_info->remote_ip.s) { |
... | ... |
@@ -99,8 +170,9 @@ int rms_sdp_prepare_new_body(rms_sdp_info_t *sdp_info, int payload_type_number) |
99 | 170 |
payload_type_number); |
100 | 171 |
body->len += strlen(sdp_m); |
101 | 172 |
|
102 |
- body->s = pkg_malloc(body->len + 1); |
|
103 |
- if (!body->s) return 0; |
|
173 |
+ body->s = shm_malloc(body->len + 1); |
|
174 |
+ if(!body->s) |
|
175 |
+ return 0; |
|
104 | 176 |
strcpy(body->s, sdp_v); |
105 | 177 |
strcat(body->s, sdp_o); |
106 | 178 |
strcat(body->s, sdp_s); |
... | ... |
@@ -110,11 +182,19 @@ int rms_sdp_prepare_new_body(rms_sdp_info_t *sdp_info, int payload_type_number) |
110 | 182 |
return 1; |
111 | 183 |
} |
112 | 184 |
|
185 |
+PayloadType * |
|
186 |
+rms_payload_type_new() // TODO: convert at the last minute from the MS manager process instead. |
|
187 |
+{ |
|
188 |
+ PayloadType *newpayload = (PayloadType *)shm_malloc(sizeof(PayloadType)); |
|
189 |
+ newpayload->flags |= PAYLOAD_TYPE_ALLOCATED; |
|
190 |
+ return newpayload; |
|
191 |
+} |
|
192 |
+ |
|
113 | 193 |
PayloadType *rms_sdp_check_payload(rms_sdp_info_t *sdp) |
114 | 194 |
{ |
115 | 195 |
// https://tools.ietf.org/html/rfc3551 |
116 | 196 |
LM_INFO("payloads[%s]\n", sdp->payloads.s); // 0 8 |
117 |
- PayloadType *pt = payload_type_new(); |
|
197 |
+ PayloadType *pt = rms_payload_type_new(); |
|
118 | 198 |
char *payloads = sdp->payloads.s; |
119 | 199 |
char *payload_type_number = strtok(payloads, " "); |
120 | 200 |
if(!payload_type_number) { |
... | ... |
@@ -168,7 +248,6 @@ PayloadType *rms_sdp_check_payload(rms_sdp_info_t *sdp) |
168 | 248 |
} |
169 | 249 |
|
170 | 250 |
|
171 |
- |
|
172 | 251 |
int rms_sdp_set_body(struct sip_msg *msg, str *new_body) |
173 | 252 |
{ |
174 | 253 |
struct lump *anchor; |
175 | 254 |
old mode 100644 |
176 | 255 |
new mode 100755 |
... | ... |
@@ -36,9 +36,11 @@ typedef struct rms_sdp_info |
36 | 36 |
int udp_local_port; |
37 | 37 |
} rms_sdp_info_t; |
38 | 38 |
|
39 |
+int rms_get_sdp_info(rms_sdp_info_t *sdp_info, struct sip_msg *msg); |
|
39 | 40 |
int rms_sdp_set_body(struct sip_msg *msg, str *new_body); |
40 | 41 |
int rms_sdp_prepare_new_body(rms_sdp_info_t *, int payload_type_number); |
41 | 42 |
void rms_sdp_info_init(rms_sdp_info_t *sdp_info); |
43 |
+int rms_sdp_info_clone(rms_sdp_info_t *dst, rms_sdp_info_t *src); |
|
42 | 44 |
void rms_sdp_info_free(rms_sdp_info_t *sdp_info); |
43 | 45 |
PayloadType *rms_sdp_check_payload(rms_sdp_info_t *); |
44 | 46 |
|
45 | 47 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,217 @@ |
1 |
+/* |
|
2 |
+ * Copyright (C) 2017-2018 Julien Chavanton jchavanton@gmail.com |
|
3 |
+ * |
|
4 |
+ * This file is part of Kamailio, a free SIP server. |
|
5 |
+ * |
|
6 |
+ * Kamailio 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 |
|
10 |
+ * |
|
11 |
+ * Kamailio is distributed in the hope that it will be useful, |
|
12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
+ * GNU General Public License for more details. |
|
15 |
+ * |
|
16 |
+ * You should have received a copy of the GNU General Public License |
|
17 |
+ * along with this program; if not, write to the Free Software |
|
18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 |
+ */ |
|
20 |
+ |
|
21 |
+#include "rtp_media_server.h" |
|
22 |
+extern rms_session_info_t *rms_session_list; |
|
23 |
+ |
|
24 |
+ |
|
25 |
+static void rms_action_free(rms_session_info_t *si) |
|
26 |
+{ |
|
27 |
+ rms_action_t *a, *tmp; |
|
28 |
+ clist_foreach(&si->action, a, next) |
|
29 |
+ { |
|
30 |
+ tmp = a; |
|
31 |
+ a = a->prev; |
|
32 |
+ clist_rm(tmp, next, prev); |
|
33 |
+ shm_free(tmp); |
|
34 |
+ } |
|
35 |
+} |
|
36 |
+ |
|
37 |
+rms_action_t *rms_action_new(rms_action_type_t t) |
|
38 |
+{ |
|
39 |
+ rms_action_t *a = shm_malloc(sizeof(rms_action_t)); |
|
40 |
+ if(!a) |
|
41 |
+ return NULL; |
|
42 |
+ memset(a, 0, sizeof(rms_action_t)); |
|
43 |
+ a->type = t; |
|
44 |
+ return a; |
|
45 |
+} |
|
46 |
+ |
|
47 |
+int init_rms_session_list() |
|
48 |
+{ |
|
49 |
+ rms_session_list = shm_malloc(sizeof(rms_session_info_t)); |
|
50 |
+ if(!rms_session_list) |
|
51 |
+ return 0; |
|
52 |
+ clist_init(rms_session_list, next, prev); |
|
53 |
+ return 1; |
|
54 |
+} |
|
55 |
+ |
|
56 |
+rms_session_info_t *rms_session_search(struct sip_msg *msg) // str *from_tag) |
|
57 |
+{ |
|
58 |
+ rms_session_info_t *si; |
|
59 |
+ str callid = msg->callid->body; |
|
60 |
+ if(parse_from_header(msg) < 0) { |
|
61 |
+ LM_ERR("can not parse from header!\n"); |
|
62 |
+ return NULL; |
|
63 |
+ } |
|
64 |
+ struct to_body *from = get_from(msg); |
|
65 |
+ clist_foreach(rms_session_list, si, next) |
|
66 |
+ { |
|
67 |
+ if(strncmp(callid.s, si->callid.s, callid.len) == 0) { |
|
68 |
+ LM_NOTICE("call-id[%s]tag[%s][%s]\n", si->callid.s, si->local_tag.s, |
|
69 |
+ si->remote_tag.s); |
|
70 |
+ if(si->remote_tag.s |
|
71 |
+ && strncmp(from->tag_value.s, si->remote_tag.s, |
|
72 |
+ from->tag_value.len) |
|
73 |
+ == 0) |
|
74 |
+ return si; |
|
75 |
+ if(si->local_tag.s |
|
76 |
+ && strncmp(from->tag_value.s, si->local_tag.s, |
|
77 |
+ from->tag_value.len) |
|
78 |
+ == 0) |
|
79 |
+ return si; |
|
80 |
+ LM_NOTICE("call-id found but tag not matching ? [%s][%.*s]\n", |
|
81 |
+ si->callid.s, from->tag_value.len, from->tag_value.s); |
|
82 |
+ } |
|
83 |
+ } |
|
84 |
+ return NULL; |
|
85 |
+} |
|
86 |
+ |
|
87 |
+rms_session_info_t *rms_session_search_sync(struct sip_msg *msg) |
|
88 |
+{ |
|
89 |
+ lock(&session_list_mutex); |
|
90 |
+ rms_session_info_t *si = rms_session_search(msg); |
|
91 |
+ unlock(&session_list_mutex); |
|
92 |
+ return si; |
|
93 |
+} |
|
94 |
+ |
|
95 |
+void rms_session_add(rms_session_info_t *si) |
|
96 |
+{ |
|
97 |
+ lock(&session_list_mutex); |
|
98 |
+ clist_append(rms_session_list, si, next, prev); |
|
99 |
+ unlock(&session_list_mutex); |
|
100 |
+} |
|
101 |
+ |
|
102 |
+void rms_session_rm(rms_session_info_t *si) |
|
103 |
+{ |
|
104 |
+ lock(&session_list_mutex); |
|
105 |
+ clist_rm(si, next, prev); |
|
106 |
+ unlock(&session_list_mutex); |
|
107 |
+} |
|
108 |
+ |
|
109 |
+int rms_session_free(rms_session_info_t *si) |
|
110 |
+{ |
|
111 |
+ rms_action_free(si); |
|
112 |
+ rms_sdp_info_free(&si->sdp_info_offer); |
|
113 |
+ rms_sdp_info_free(&si->sdp_info_answer); |
|
114 |
+ if(si->media.pt) { |
|
115 |
+ // payload_type_destroy(si->media.pt); |
|
116 |
+ shm_free( |
|
117 |
+ si->media |
|
118 |
+ .pt); // TODO: should be destroyed in compatible way from MS manager process |
|
119 |
+ si->media.pt = NULL; |
|
120 |
+ } |
|
121 |
+ if(si->callid.s) { |
|
122 |
+ shm_free(si->callid.s); |
|
123 |
+ si->callid.s = NULL; |
|
124 |
+ } |
|
125 |
+ if(si->contact_uri.s) { |
|
126 |
+ shm_free(si->contact_uri.s); |
|
127 |
+ si->contact_uri.s = NULL; |
|
128 |
+ } |
|
129 |
+ if(si->local_ip.s) { |
|
130 |
+ shm_free(si->local_ip.s); |
|
131 |
+ si->local_ip.s = NULL; |
|
132 |
+ } |
|
133 |
+ if(si->remote_uri.s) { |
|
134 |
+ shm_free(si->remote_uri.s); |
|
135 |
+ si->remote_uri.s = NULL; |
|
136 |
+ } |
|
137 |
+ if(si->local_uri.s) { |
|
138 |
+ shm_free(si->local_uri.s); |
|
139 |
+ si->local_uri.s = NULL; |
|
140 |
+ } |
|
141 |
+ shm_free(si); |
|
142 |
+ si = NULL; |
|
143 |
+ return 1; |
|
144 |
+} |
|
145 |
+ |
|
146 |
+int rms_check_msg(struct sip_msg *msg) |
|
147 |
+{ |
|
148 |
+ if(!msg || !msg->callid || !msg->callid->body.s) { |
|
149 |
+ LM_INFO("no callid ?\n"); |
|
150 |
+ return -1; |
|
151 |
+ } |
|
152 |
+ return 1; |
|
153 |
+} |
|
154 |
+ |
|
155 |
+rms_session_info_t *rms_session_new(struct sip_msg *msg) |
|
156 |
+{ |
|
157 |
+ struct hdr_field *hdr = NULL; |
|
158 |
+ |
|
159 |
+ if(!rms_check_msg(msg)) |
|
160 |
+ return NULL; |
|
161 |
+ rms_session_info_t *si = shm_malloc(sizeof(rms_session_info_t)); |
|
162 |
+ if(!si) { |
|
163 |
+ LM_ERR("can not allocate session info !\n"); |
|
164 |
+ goto error; |
|
165 |
+ } |
|
166 |
+ memset(si, 0, sizeof(rms_session_info_t)); |
|
167 |
+ |
|
168 |
+ if(!rms_str_dup(&si->callid, &msg->callid->body, 1)) { |
|
169 |
+ LM_ERR("can not get callid .\n"); |
|
170 |
+ goto error; |
|
171 |
+ } |
|
172 |
+ if(!rms_str_dup(&si->remote_uri, &msg->from->body, 1)) |
|
173 |
+ goto error; |
|
174 |
+ if(!rms_str_dup(&si->local_uri, &msg->to->body, 1)) |
|
175 |
+ goto error; |
|
176 |
+ str ip; |
|
177 |
+ ip.s = ip_addr2a(&msg->rcv.dst_ip); |
|
178 |
+ ip.len = strlen(ip.s); |
|
179 |
+ if(!rms_str_dup(&si->local_ip, &ip, 1)) |
|
180 |
+ goto error; |
|
181 |
+ hdr = msg->contact; |
|
182 |
+ if(parse_contact(hdr) < 0) |
|
183 |
+ goto error; |
|
184 |
+ contact_body_t *contact = hdr->parsed; |
|
185 |
+ if(!rms_str_dup(&si->contact_uri, &contact->contacts->uri, 1)) |
|
186 |
+ goto error; |
|
187 |
+ LM_INFO("[contact offer] [%.*s]\n", si->contact_uri.len, si->contact_uri.s); |
|
188 |
+ si->cseq = atoi(msg->cseq->body.s); |
|
189 |
+ |
|
190 |
+ rms_sdp_info_t *sdp_info = &si->sdp_info_offer; |
|
191 |
+ if(!rms_get_sdp_info(sdp_info, msg)) |
|
192 |
+ goto error; |
|
193 |
+ si->media.pt = rms_sdp_check_payload(sdp_info); |
|
194 |
+ if(!si->media.pt) { |
|
195 |
+ tmb.t_reply(msg, 488, "incompatible media format"); |
|
196 |
+ goto error; |
|
197 |
+ } |
|
198 |
+ clist_init(&si->action, next, prev); |
|
199 |
+ return si; |
|
200 |
+error: |
|
201 |
+ LM_ERR("can not create session.\n"); |
|
202 |
+ rms_session_free(si); |
|
203 |
+ return NULL; |
|
204 |
+} |
|
205 |
+ |
|
206 |
+int rms_sessions_dump_f(struct sip_msg *msg, char *param1, char *param2) |
|
207 |
+{ |
|
208 |
+ int x = 1; |
|
209 |
+ rms_session_info_t *si; |
|
210 |
+ clist_foreach(rms_session_list, si, next) |
|
211 |
+ { |
|
212 |
+ LM_INFO("[%d]callid[%s]remote_tag[%s]local_tag[%s]cseq[%d]\n", x, |
|
213 |
+ si->callid.s, si->remote_tag.s, si->local_tag.s, si->cseq); |
|
214 |
+ x++; |
|
215 |
+ } |
|
216 |
+ return 1; |
|
217 |
+} |
0 | 218 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,107 @@ |
1 |
+/* |
|
2 |
+ * Copyright (C) 2017-2018 Julien Chavanton jchavanton@gmail.com |
|
3 |
+ * |
|
4 |
+ * This file is part of Kamailio, a free SIP server. |
|
5 |
+ * |
|
6 |
+ * Kamailio 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 |
|
10 |
+ * |
|
11 |
+ * Kamailio is distributed in the hope that it will be useful, |
|
12 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 |
+ * GNU General Public License for more details. |
|
15 |
+ * |
|
16 |
+ * You should have received a copy of the GNU General Public License |
|
17 |
+ * along with this program; if not, write to the Free Software |
|
18 |
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
|
19 |
+ */ |
|
20 |
+ |
|
21 |
+#ifndef rms_session_info_h |
|
22 |
+#define rms_session_info_h |
|
23 |
+// #include "rtp_media_server.h" |
|
24 |
+#include "rms_media.h" |
|
25 |
+//typedef struct rms_action rms_action_t; |
|
26 |
+typedef struct rms_session_info rms_session_info_t; |
|
27 |
+// struct call_leg_media; |
|
28 |
+// typedef struct call_leg_media call_leg_media_t; |
|
29 |
+ |
|
30 |
+typedef enum rms_action_type { |
|
31 |
+ RMS_NONE, |
|
32 |
+ RMS_START, |
|
33 |
+ RMS_STOP, |
|
34 |
+ RMS_HANGUP, |
|
35 |
+ RMS_PLAY, |
|
36 |
+ RMS_BRIDGING, |
|
37 |
+ RMS_BRIDGED, |
|
38 |
+ RMS_DONE, |
|
39 |
+} rms_action_type_t; |
|
40 |
+ |
|
41 |
+typedef struct rms_tm_info |
|
42 |
+{ |
|
43 |
+ unsigned int hash_index; |
|
44 |
+ unsigned int label; |
|
45 |
+} rms_tm_info_t; |
|
46 |
+ |
|
47 |
+typedef struct rms_action |
|
48 |
+{ |
|
49 |
+ struct rms_action *next; |
|
50 |
+ struct rms_action *prev; |
|
51 |
+ str param; |
|
52 |
+ str route; |
|
53 |
+ rms_action_type_t type; |
|
54 |
+ rms_tm_info_t tm_info; |
|
55 |
+ struct rms_session_info *si; |
|
56 |
+ struct cell *cell; |
|
57 |
+} rms_action_t; |
|
58 |
+ |
|
59 |
+int rms_check_msg(struct sip_msg *msg); |
|
60 |
+rms_action_t *rms_action_new(rms_action_type_t t); |
|
61 |
+int init_rms_session_list(); |
|
62 |
+rms_session_info_t *rms_session_search(struct sip_msg *msg); |
|
63 |
+rms_session_info_t *rms_session_search_sync(struct sip_msg *msg); |
|
64 |
+void rms_session_add(rms_session_info_t *si); |
|
65 |
+void rms_session_rm(rms_session_info_t *si); |
|
66 |
+int rms_session_free(rms_session_info_t *si); |
|
67 |
+rms_session_info_t *rms_session_new(struct sip_msg *msg); |
|
68 |
+int rms_sessions_dump_f(struct sip_msg *msg, char *param1, char *param2); |
|
69 |
+rms_session_info_t *rms_get_session_list(void); |
|
70 |
+ |
|
71 |
+typedef struct ms_res |
|
72 |
+{ |
|
73 |
+ AudioStream *audio_stream; |
|
74 |
+ RtpProfile *rtp_profile; |
|
75 |
+} ms_res_t; |
|
76 |
+ |
|
77 |
+typedef enum rms_session_state { |
|
78 |
+ RMS_ST_DEFAULT, |
|
79 |
+ RMS_ST_CONNECTING, |
|
80 |
+ RMS_ST_CONNECTED, |
|
81 |
+ RMS_ST_DISCONNECTING, |
|
82 |
+ RMS_ST_DISCONNECTED, |
|
83 |
+} rms_session_state_t; |
|
84 |
+ |
|
85 |
+typedef struct rms_session_info |
|
86 |
+{ |
|
87 |
+ struct rms_session_info *next; |
|
88 |
+ struct rms_session_info *prev; |
|
89 |
+ rms_sdp_info_t sdp_info_offer; |
|
90 |
+ rms_sdp_info_t sdp_info_answer; |
|
91 |
+ str callid; |
|
92 |
+ str local_ip; |
|
93 |
+ int local_port; |
|
94 |
+ str local_uri; |
|
95 |
+ str local_tag; |
|
96 |
+ str remote_uri; |
|
97 |
+ str remote_tag; |
|
98 |
+ str contact_uri; |
|
99 |
+ int cseq; |
|
100 |
+ ms_res_t ms; |
|
101 |
+ call_leg_media_t media; |
|
102 |
+ rms_action_t action; |
|
103 |
+ rms_session_info_t *bridged_si; |
|
104 |
+ rms_session_state_t state; |
|
105 |
+} rms_session_info_t; |
|
106 |
+ |
|
107 |
+#endif |
... | ... |
@@ -33,7 +33,7 @@ static inline int rms_str_dup(str *dst, str *src, int shared) |
33 | 33 |
{ |
34 | 34 |
if(!dst) { |
35 | 35 |
LM_ERR("dst null\n"); |
36 |
- return -1; |
|
36 |
+ return 0; |
|
37 | 37 |
} |
38 | 38 |
dst->len = 0; |
39 | 39 |
dst->s = NULL; |
... | ... |
@@ -45,21 +45,21 @@ static inline int rms_str_dup(str *dst, str *src, int shared) |
45 | 45 |
return 1; |
46 | 46 |
dst->len = src->len; |
47 | 47 |
if(shared) { |
48 |
- dst->s = shm_malloc(dst->len+1); |
|
48 |
+ dst->s = shm_malloc(dst->len + 1); |
|
49 | 49 |
} else { |
50 |
- dst->s = pkg_malloc(dst->len+1); |
|
50 |
+ dst->s = pkg_malloc(dst->len + 1); |
|
51 | 51 |
} |
52 | 52 |
if(!dst->s) { |
53 | 53 |
LM_ERR("%s_malloc: can't allocate memory (%d bytes)\n", |
54 | 54 |
shared ? "shm" : "pkg", src->len); |
55 |
- return -1; |
|
55 |
+ return 0; |
|
56 | 56 |
} |
57 | 57 |
memcpy(dst->s, src->s, src->len); |
58 | 58 |
dst->s[dst->len] = '\0'; |
59 | 59 |
return 1; |
60 | 60 |
} |
61 | 61 |
|
62 |
-static inline char* rms_char_dup(char *s, int shared) |
|
62 |
+static inline char *rms_char_dup(char *s, int shared) |
|
63 | 63 |
{ |
64 | 64 |
str src; |
65 | 65 |
str dst; |
... | ... |
@@ -23,39 +23,44 @@ |
23 | 23 |
|
24 | 24 |
MODULE_VERSION |
25 | 25 |
|
26 |
+rms_session_info_t *rms_session_list; |
|
26 | 27 |
static int mod_init(void); |
27 | 28 |
static void mod_destroy(void); |
28 | 29 |
static int child_init(int); |
29 |
- |
|
30 |
-static rms_session_info_t *rms_session_list; |
|
31 | 30 |
str playback_fn = {0, 0}; |
32 | 31 |
str log_fn = {0, 0}; |
33 | 32 |
|
34 | 33 |
static rms_t rms; |
35 | 34 |
|
36 |
-static int rms_session_free(rms_session_info_t *si); |
|
37 |
-static rms_session_info_t *rms_session_search(char *callid, int len); |
|
35 |
+static rms_session_info_t *rms_session_create_leg(rms_session_info_t *si); |
|
38 | 36 |
static int fixup_rms_action_play(void **param, int param_no); |
37 |
+static int fixup_rms_bridge(void **param, int param_no); |
|
39 | 38 |
static int rms_hangup_call(rms_session_info_t *si); |
39 |
+static int rms_bridging_call(rms_session_info_t *si, rms_action_t *a); |
|
40 |
+static int rms_bridged_call(rms_session_info_t *si, rms_action_t *a); |
|
40 | 41 |
|
41 | 42 |
static int rms_answer_f(struct sip_msg *); |
43 |
+static int rms_sip_request_f(struct sip_msg *); |
|
42 | 44 |
static int rms_action_play_f(struct sip_msg *, str *, str *); |
43 |
-static int rms_sdp_offer_f(struct sip_msg *, char *, char *); |
|
44 |
-static int rms_sdp_answer_f(struct sip_msg *, char *, char *); |
|
45 |
-static int rms_media_stop_f(struct sip_msg *, char *, char *); |
|
45 |
+static int rms_session_check_f(struct sip_msg *); |
|
46 | 46 |
static int rms_hangup_f(struct sip_msg *); |
47 |
-static int rms_sessions_dump_f(struct sip_msg *, char *, char *); |
|
47 |
+static int rms_bridge_f(struct sip_msg *, char *, str *); |
|
48 |
+ |
|
49 |
+static int rms_update_call_sdp(struct sip_msg *msg, |
|
50 |
+ const rms_session_info_t *si, call_leg_media_t *m, |
|
51 |
+ rms_sdp_info_t *sdp_info); |
|
48 | 52 |
|
49 | 53 |
static cmd_export_t cmds[] = { |
50 | 54 |
{"rms_answer", (cmd_function)rms_answer_f, 0, 0, 0, EVENT_ROUTE}, |
51 |
- {"rms_play", (cmd_function)rms_action_play_f, 2, fixup_rms_action_play, 0, |
|
52 |
- ANY_ROUTE}, |
|
53 |
- {"rms_sdp_offer", (cmd_function)rms_sdp_offer_f, 0, 0, 0, ANY_ROUTE}, |
|
54 |
- {"rms_sdp_answer", (cmd_function)rms_sdp_answer_f, 0, 0, 0, REQUEST_ROUTE |
|
55 |
- | FAILURE_ROUTE | ONREPLY_ROUTE}, |
|
56 |
- {"rms_media_stop", (cmd_function)rms_media_stop_f, 0, 0, 0, REQUEST_ROUTE |
|
57 |
- | FAILURE_ROUTE | ONREPLY_ROUTE}, |
|
55 |
+ {"rms_sip_request", (cmd_function)rms_sip_request_f, 0, 0, 0, |
|
56 |
+ EVENT_ROUTE}, |
|
57 |
+ {"rms_play", (cmd_function)rms_action_play_f, 2, fixup_rms_action_play, |
|
58 |
+ 0, ANY_ROUTE}, |
|
59 |
+ {"rms_session_check", (cmd_function)rms_session_check_f, 0, 0, 0, |
|
60 |
+ REQUEST_ROUTE | FAILURE_ROUTE | ONREPLY_ROUTE}, |
|
58 | 61 |
{"rms_hangup", (cmd_function)rms_hangup_f, 0, 0, 0, EVENT_ROUTE}, |
62 |
+ {"rms_bridge", (cmd_function)rms_bridge_f, 2, fixup_rms_bridge, 0, |
|
63 |
+ ANY_ROUTE}, |
|
59 | 64 |
{"rms_sessions_dump", (cmd_function)rms_sessions_dump_f, 0, 0, 0, |
60 | 65 |
ANY_ROUTE}, |
61 | 66 |
{0, 0, 0, 0, 0, 0}}; |
... | ... |
@@ -89,12 +94,31 @@ static void run_action_route(rms_session_info_t *si, char *route) |
89 | 94 |
LM_ERR("faked_msg_init() failed\n"); |
90 | 95 |
return; |
91 | 96 |
} |
97 |
+ |
|
92 | 98 |
fmsg = faked_msg_next(); |
93 |
- struct hdr_field callid; |
|
94 |
- callid.body.s = si->callid.s; |
|
95 |
- callid.body.len = si->callid.len; |
|
96 | 99 |
|
97 |
- fmsg->callid = &callid; |
|
100 |
+ { // set the callid |
|
101 |
+ struct hdr_field callid; |
|
102 |
+ callid.body.s = si->callid.s; |
|
103 |
+ callid.body.len = si->callid.len; |
|
104 |
+ fmsg->callid = &callid; |
|
105 |
+ } |
|
106 |
+ { // set the from tag |
|
107 |
+ struct hdr_field from; |
|
108 |
+ struct to_body from_parsed; |
|
109 |
+ from.parsed = &from_parsed; |
|
110 |
+ from_parsed.tag_value.len = si->remote_tag.len; |
|
111 |
+ from_parsed.tag_value.s = si->remote_tag.s; |
|
112 |
+ fmsg->from = &from; |
|
113 |
+ } |
|
114 |
+ //{ // set the to tag |
|
115 |
+ // struct hdr_field to; |
|
116 |
+ // struct to_body to_parsed; |
|
117 |
+ // to.parsed = &to_parsed; |
|
118 |
+ // to_parsed.tag_value.len = si->local_tag.len; |
|
119 |
+ // to_parsed.tag_value.s = si->local_tag.s; |
|
120 |
+ // fmsg->to = &to; |
|
121 |
+ //} |
|
98 | 122 |
|
99 | 123 |
backup_rt = get_route_type(); |
100 | 124 |
set_route_type(EVENT_ROUTE); |
... | ... |
@@ -105,6 +129,17 @@ static void run_action_route(rms_session_info_t *si, char *route) |
105 | 129 |
set_route_type(backup_rt); |
106 | 130 |
} |
107 | 131 |
|
132 |
+ |
|
133 |
+static int fixup_rms_bridge(void **param, int param_no) |
|
134 |
+{ |
|
135 |
+ if(param_no == 1) |
|
136 |
+ return fixup_spve_null(param, 1); |
|
137 |
+ if(param_no == 2) |
|
138 |
+ return fixup_spve_null(param, 1); |
|
139 |
+ LM_ERR("invalid parameter count [%d]\n", param_no); |
|
140 |
+ return -1; |
|
141 |
+} |
|
142 |
+ |
|
108 | 143 |
static int fixup_rms_action_play(void **param, int param_no) |
109 | 144 |
{ |
110 | 145 |
if(param_no == 1) |
... | ... |
@@ -123,11 +158,15 @@ static int mod_init(void) |
123 | 158 |
{ |
124 | 159 |
LM_INFO("RTP media server module init\n"); |
125 | 160 |
rms.udp_start_port = 50000; |
161 |
+ LM_INFO("RTP media server module init\n"); |
|
126 | 162 |
rms.udp_end_port = 60000; |
127 |
- rms.udp_last_port = 50000; |
|
163 |
+ rms.udp_last_port = 50000 + rand() % 10000; |
|
128 | 164 |
rms_media_init(); |
129 |
- rms_session_list = shm_malloc(sizeof(rms_session_info_t)); |
|
130 |
- clist_init(rms_session_list, next, prev); |
|
165 |
+ |
|
166 |
+ if(!init_rms_session_list()) { |
|
167 |
+ LM_ERR("can't initialize rms_session_list !\n"); |
|
168 |
+ return -1; |
|
169 |
+ } |
|
131 | 170 |
|
132 | 171 |
register_procs(1); |
133 | 172 |
if(load_tm_api(&tmb) != 0) { |
... | ... |
@@ -163,7 +202,26 @@ void rms_signal_handler(int signum) |
163 | 202 |
LM_INFO("signal received [%d]\n", signum); |
164 | 203 |
} |
165 | 204 |
|
166 |
-static rms_session_info_t* rms_session_action_check(rms_session_info_t *si) |
|
205 |
+ |
|
206 |
+static rms_session_info_t *rms_stop(rms_session_info_t *si) |
|
207 |
+{ |
|
208 |
+ LM_NOTICE("si[%p]\n", si); |
|
209 |
+ if(si->bridged_si) { |
|
210 |
+ rms_stop_bridge(&si->media, &si->bridged_si->media); |
|
211 |
+ } else { |
|
212 |
+ rms_stop_media(&si->media); |
|
213 |
+ } |
|
214 |
+ |
|
215 |
+ rms_session_info_t *tmp = si->prev; |
|
216 |
+ si->state = RMS_ST_DISCONNECTED; |
|
217 |
+ // keep it for a little while to deal with retransmissions ... |
|
218 |
+ //clist_rm(si, next, prev); |
|
219 |
+ //rms_session_free(si); |
|
220 |
+ si = tmp; |
|
221 |
+ return si; |
|
222 |
+} |
|
223 |
+ |
|
224 |
+static rms_session_info_t *rms_session_action_check(rms_session_info_t *si) |
|
167 | 225 |
{ |
168 | 226 |
rms_action_t *a; |
169 | 227 |
clist_foreach(&si->action, a, next) |
... | ... |
@@ -171,19 +229,35 @@ static rms_session_info_t* rms_session_action_check(rms_session_info_t *si) |
171 | 229 |
if(a->type == RMS_HANGUP) { |
172 | 230 |
LM_INFO("session action RMS_HANGUP [%s]\n", si->callid.s); |
173 | 231 |
rms_hangup_call(si); |
232 |
+ if(si->bridged_si) |
|
233 |
+ rms_hangup_call(si->bridged_si); |
|
174 | 234 |
a->type = RMS_STOP; |
175 | 235 |
return si; |
236 |
+ } else if(a->type == RMS_BRIDGING) { |
|
237 |
+ LM_INFO("session action RMS_BRIDGING [%s][%p]\n", si->callid.s, |
|
238 |
+ a->cell->uas.request); |
|
239 |
+ rms_bridging_call(si, a); |
|
240 |
+ a->type = RMS_NONE; |
|
241 |
+ shm_free(a->param.s); |
|
242 |
+ return si; |
|
243 |
+ } else if(a->type == RMS_BRIDGED) { |
|
244 |
+ LM_INFO("session action RMS_BRIDGED [%s]\n", si->callid.s); |
|
245 |
+ LM_INFO("si_1[%p]si_2[%p]\n", si, si->bridged_si); |
|
246 |
+ rms_bridged_call(si, a); |
|
247 |
+ a->type = RMS_NONE; |
|
248 |
+ return si; |
|
176 | 249 |
} else if(a->type == RMS_STOP) { |
177 |
- LM_INFO("session action RMS_STOP [%s][%p|%p]\n", si->callid.s, si, si->prev); |
|
178 |
- rms_stop_media(&si->caller_media); |
|
179 |
- rms_session_info_t *tmp = si->prev; |
|
180 |
- clist_rm(si, next, prev); |
|
181 |
- rms_session_free(si); |
|
182 |
- si = tmp; |
|
250 |
+ LM_INFO("session action RMS_STOP [%s][%p|%p]\n", si->callid.s, si, |
|
251 |
+ si->prev); |
|
252 |
+ //if (si->bridged_si) |
|
253 |
+ // rms_stop(si->bridged_si); |
|
254 |
+ si = rms_stop(si); |
|
255 |
+ a->type = RMS_NONE; |
|
256 |
+ // si->state = RMS_SSTATE_DISCONNECTED; |
|
183 | 257 |
return si; |
184 | 258 |
} else if(a->type == RMS_PLAY) { |
185 | 259 |
LM_INFO("session action RMS_PLAY [%s]\n", si->callid.s); |
186 |
- rms_playfile(&si->caller_media, a); |
|
260 |
+ rms_playfile(&si->media, a); |
|
187 | 261 |
a->type = RMS_NONE; |
188 | 262 |
} else if(a->type == RMS_DONE) { |
189 | 263 |
LM_INFO("session action RMS_DONE [%s][%s]\n", si->callid.s, |
... | ... |
@@ -199,9 +273,9 @@ static rms_session_info_t* rms_session_action_check(rms_session_info_t *si) |
199 | 273 |
} |
200 | 274 |
return si; |
201 | 275 |
} else if(a->type == RMS_START) { |
202 |
- create_call_leg_media(&si->caller_media); |
|
276 |
+ create_call_leg_media(&si->media); |
|
203 | 277 |
LM_INFO("session action RMS_START [%s]\n", si->callid.s); |
204 |
- rms_start_media(&si->caller_media, a->param.s); |
|
278 |
+ rms_start_media(&si->media, a->param.s); |
|
205 | 279 |
run_action_route(si, "rms:start"); |
206 | 280 |
a->type = RMS_NONE; |
207 | 281 |
return si; |
... | ... |
@@ -225,7 +299,7 @@ static void rms_session_manage_loop() |
225 | 299 |
si = rms_session_action_check(si); |
226 | 300 |
} |
227 | 301 |
unlock(&session_list_mutex); |
228 |
- usleep(2000); |
|
302 |
+ usleep(10000); |
|
229 | 303 |
} |
230 | 304 |
} |
231 | 305 |
|
... | ... |
@@ -259,130 +333,264 @@ static int child_init(int rank) |
259 | 333 |
return (rtn); |
260 | 334 |
} |
261 | 335 |
|
262 |
-static int rms_get_sdp_info(rms_sdp_info_t *sdp_info, struct sip_msg *msg) |
|
336 |
+static int parse_from(struct sip_msg *msg, rms_session_info_t *si) |
|
263 | 337 |
{ |
264 |
- sdp_session_cell_t *sdp_session; |
|
265 |
- sdp_stream_cell_t *sdp_stream; |
|
266 |
- str media_ip, media_port; |
|
267 |
- int sdp_session_num = 0; |
|
268 |
- int sdp_stream_num = get_sdp_stream_num(msg); |
|
269 |
- if(parse_sdp(msg) < 0) { |
|
270 |
- LM_INFO("can not parse sdp\n"); |
|
271 |
- return 0; |
|
272 |
- } |
|
273 |
- sdp_info_t *sdp = (sdp_info_t *)msg->body; |
|
274 |
- if(!sdp) { |
|
275 |
- LM_INFO("sdp null\n"); |
|
338 |
+ struct to_body *from = get_from(msg); |
|
339 |
+ LM_DBG("from[%.*s]tag[%.*s]\n", from->uri.len, from->uri.s, |
|
340 |
+ from->tag_value.len, from->tag_value.s); |
|
341 |
+ rms_str_dup(&si->remote_tag, &from->tag_value, 1); |
|
342 |
+ return 1; |
|
343 |
+} |
|
344 |
+ |
|
345 |
+static int rms_sip_reply( |
|
346 |
+ struct cell *cell, rms_session_info_t *si, int code, char *_reason) |
|
347 |
+{ |
|
348 |
+ str reason = str_init(_reason); |
|
349 |
+ if(si->remote_tag.len == 0) { |
|
350 |
+ LM_ERR("can not find from tag\n"); |
|
276 | 351 |
return 0; |
277 | 352 |
} |
278 |
- rms_str_dup(&sdp_info->recv_body, &sdp->text, 1); |
|
279 |
- if(!sdp_info->recv_body.s) |
|
280 |
- goto error; |
|
281 |
- LM_INFO("sdp body - type[%d]\n", sdp->type); |
|
282 |
- if(sdp_stream_num > 1 || !sdp_stream_num) { |
|
283 |
- LM_INFO("only support one stream[%d]\n", sdp_stream_num); |
|
284 |
- } |
|
285 |
- sdp_stream_num = 0; |
|
286 |
- sdp_session = get_sdp_session(msg, sdp_session_num); |
|
287 |
- if(!sdp_session) { |
|
288 |
- return 0; |
|
289 |
- } else { |
|
290 |
- int sdp_stream_num = 0; |
|
291 |
- sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num); |
|
292 |
- if(!sdp_stream) { |
|
293 |
- LM_INFO("can not get the sdp stream\n"); |
|
353 |
+ |
|
354 |
+ if(!cell) |
|
355 |
+ cell = tmb.t_gett(); |
|
356 |
+ |
|
357 |
+ if(cell->uas.request) { |
|
358 |
+ if(!tmb.t_reply_with_body( |
|
359 |
+ cell, code, &reason, NULL, NULL, &si->local_tag)) { |
|
360 |
+ LM_ERR("t_reply error"); |
|
294 | 361 |
return 0; |
295 |
- } else { |
|
296 |
- rms_str_dup(&sdp_info->payloads, &sdp_stream->payloads, 1); |
|
297 |
- if(!sdp_info->payloads.s) |
|
298 |
- goto error; |
|
299 | 362 |
} |
300 |
- } |
|
301 |
- if(sdp_stream->ip_addr.s && sdp_stream->ip_addr.len > 0) { |
|
302 |
- media_ip = sdp_stream->ip_addr; |
|
303 | 363 |
} else { |
304 |
- media_ip = sdp_session->ip_addr; |
|
364 |
+ LM_INFO("no request found\n"); |
|
305 | 365 |
} |
306 |
- rms_str_dup(&sdp_info->remote_ip, &media_ip, 1); |
|
307 |
- if(!sdp_info->remote_ip.s) |
|
308 |
- goto error; |
|
309 |
- rms_str_dup(&media_port, &sdp_stream->port, 0); |
|
310 |
- if(!media_port.s) |
|
311 |
- goto error; |
|
312 |
- sdp_info->remote_port = atoi(media_port.s); |
|
313 |
- pkg_free(media_port.s); |
|
314 | 366 |
return 1; |
315 |
-error: |
|
316 |
- rms_sdp_info_free(sdp_info); |
|
317 |
- return 0; |
|
318 | 367 |
} |
319 | 368 |
|
320 |
-static int rms_relay_call(struct sip_msg *msg) |
|
369 |
+static int rms_answer_call( |
|
370 |
+ struct cell *cell, rms_session_info_t *si, rms_sdp_info_t *sdp_info) |
|
321 | 371 |
{ |
322 |
- if(!tmb.t_relay(msg, NULL, NULL)) { |
|
323 |
- LM_INFO("t_ralay error\n"); |
|
324 |
- return -1; |
|
372 |
+ char buffer[128]; |
|
373 |
+ str reason = str_init("OK"); |
|
374 |
+ str contact_hdr; |
|
375 |
+ |
|
376 |
+ LM_INFO("[%s][%d]\n", sdp_info->new_body.s, sdp_info->udp_local_port); |
|
377 |
+ |
|
378 |
+ if(si->remote_tag.len == 0) { |
|
379 |
+ LM_ERR("can not find from tag\n"); |
|
380 |
+ return 0; |
|
381 |
+ } |
|
382 |
+ LM_INFO("ip[%s]\n", si->local_ip.s); |
|
383 |
+ sdp_info->local_ip.s = si->local_ip.s; |
|
384 |
+ sdp_info->local_ip.len = si->local_ip.len; |
|
385 |
+ |
|
386 |
+ snprintf(buffer, 128, |
|
387 |
+ "Contact: <sip:rms@%s:%d>\r\nContent-Type: application/sdp\r\n", |
|
388 |
+ si->local_ip.s, si->local_port); |
|
389 |
+ contact_hdr.len = strlen(buffer); |
|
390 |
+ contact_hdr.s = buffer; |
|
391 |
+ |
|
392 |
+ if(!cell) |
|
393 |
+ cell = tmb.t_gett(); |
|
394 |
+ |
|
395 |
+ if(cell->uas.request) { |
|
396 |
+ if(!tmb.t_reply_with_body(cell, 200, &reason, &sdp_info->new_body, |
|
397 |
+ &contact_hdr, &si->local_tag)) { |
|
398 |
+ LM_ERR("t_reply error"); |
|
399 |
+ return 0; |
|
400 |
+ } |
|
401 |
+ LM_INFO("answered\n"); |
|
402 |
+ } else { |
|
403 |
+ LM_INFO("no request found\n"); |
|
325 | 404 |
} |
326 | 405 |
return 1; |
327 | 406 |
} |
328 | 407 |
|
329 |
-static int parse_from(struct sip_msg *msg, rms_session_info_t *si) |
|
408 |
+// message originating leg is suspended, this is the callback function of the transaction with destination leg |
|
409 |
+static void forward_cb(struct cell *ptrans, int ntype, struct tmcb_params *pcbp) |
|
330 | 410 |
{ |
331 |
- struct to_body *from = get_from(msg); |
|
332 |
- LM_INFO("from[%.*s]tag[%.*s]\n", from->uri.len, from->uri.s, |
|
333 |
- from->tag_value.len, from->tag_value.s); |
|
334 |
- rms_str_dup(&si->remote_tag, &from->tag_value, 1); |
|
335 |
- return 1; |
|
411 |
+ // struct sip_msg *msg = pcbp->rpl; |
|
412 |
+ str *reason = &pcbp->rpl->first_line.u.reply.reason; |
|
413 |
+ rms_action_t *a = (rms_action_t *)*pcbp->param; |
|
414 |
+ if(ntype == TMCB_ON_FAILURE) { |
|
415 |
+ LM_NOTICE("FAILURE [%d][%.*s]\n", pcbp->code, reason->len, reason->s); |
|
416 |
+ return; |
|
417 |
+ } else { |
|
418 |
+ LM_NOTICE("COMPLETE [%d][%.*s] RE-INVITE/UPDATE - TODO SDP " |
|
419 |
+ "renegotiation ? \n", |
|
420 |
+ pcbp->code, reason->len, reason->s); |
|
421 |
+ } |
|
422 |
+ |
|
423 |
+ // rms_answer_call(a->cell, si, sdp_info); |
|
424 |
+ // if(!cell) cell = tmb.t_gett(); |
|
425 |
+ if(a->cell->uas.request) { |
|
426 |
+ if(!tmb.t_reply_with_body(a->cell, pcbp->code, reason, NULL, NULL, |
|
427 |
+ &a->si->local_tag)) { |
|
428 |
+ LM_ERR("t_reply error"); |
|
429 |
+ return; |
|
430 |
+ } |
|
431 |
+ LM_INFO("replied\n"); |
|
432 |
+ } else { |
|
433 |
+ LM_INFO("no request found\n"); |
|
434 |
+ } |
|
336 | 435 |
} |
337 | 436 |
|
338 |
-static int rms_answer_call(struct sip_msg *msg, rms_session_info_t *si) |
|
339 |
-{ |
|
340 |
- char buffer[128]; |
|
341 |
- str to_tag; |
|
342 |
- str reason = str_init("OK"); |
|
343 |
- str contact_hdr; |
|
344 | 437 |
|
345 |
- rms_sdp_info_t *sdp_info = &si->sdp_info_offer; |
|
438 |
+// legA is suspended, this is the callback function of the transaction with legB (the callee) |
|
439 |
+// response to legA will be not be done here but once the media negociation is completed by the RMS process. |
|
440 |
+static void bridge_cb(struct cell *ptrans, int ntype, struct tmcb_params *pcbp) |
|
441 |
+{ |
|
442 |
+ struct sip_msg *msg = pcbp->rpl; |
|
443 |
+ if(ntype == TMCB_ON_FAILURE) { |
|
444 |
+ LM_NOTICE("FAILURE [%d]\n", pcbp->code); |
|
445 |
+ rms_action_t *a = (rms_action_t *)*pcbp->param; |
|
446 |
+ a->si->state = RMS_ST_DISCONNECTED; |
|
447 |
+ if(a->cell->uas.request) { |
|
448 |
+ str *reason = &pcbp->rpl->first_line.u.reply.reason; |
|
449 |
+ if(!tmb.t_reply_with_body(a->cell, pcbp->code, reason, NULL, NULL, |
|
450 |
+ &a->si->local_tag)) { |
|
451 |
+ LM_ERR("t_reply error"); |
|
452 |
+ return; |
|
453 |
+ } |
|
454 |
+ LM_INFO("failure replied\n"); |
|
455 |
+ a->type = RMS_NONE; |
|
456 |
+ } else { |
|
457 |
+ LM_ERR("failure but no request found\n"); |
|
458 |
+ } |
|
459 |
+ return; |
|
460 |
+ } else if(ntype == TMCB_LOCAL_COMPLETED) { |
|
461 |
+ LM_NOTICE("COMPLETED [%d]\n", pcbp->code); |
|
462 |
+ } else { |
|
463 |
+ LM_NOTICE("TMCB_TYPE[%d][%d]\n", ntype, pcbp->code); |
|
464 |
+ } |
|
346 | 465 |
|
347 |
- if(msg->REQ_METHOD != METHOD_INVITE) { |
|
348 |
- LM_ERR("only invite is supported for offer \n"); |
|
349 |
- return 0; |
|
466 |
+ if(parse_to_header(msg) < 0) { |
|
467 |
+ LM_ERR("can not parse To header!\n"); |
|
468 |
+ return; |
|
350 | 469 |
} |
470 |
+ struct to_body *to = get_to(msg); |
|
471 |
+ if(parse_from_header(msg) < 0) { |
|
472 |
+ LM_ERR("can not parse From header!\n"); |
|
473 |
+ return; |
|
474 |
+ } |
|
475 |
+ struct to_body *from = get_from(msg); |
|
351 | 476 |
|
352 |
- parse_from(msg, si); |
|
477 |
+ rms_action_t *a = (rms_action_t *)*pcbp->param; |
|
478 |
+ rms_session_info_t *bridged_si = a->si; |
|
479 |
+ rms_session_info_t *si = bridged_si->bridged_si; |
|
353 | 480 |
|
354 |
- if(si->remote_tag.len == 0) { |
|
355 |
- LM_ERR("can not find from tag\n"); |
|
356 |
- return 0; |
|
481 |
+ if(to->tag_value.len == 0) { |
|
482 |
+ LM_ERR("not to tag.\n"); |
|
483 |
+ goto error; |
|