/src/pjsip/pjsip/src/pjsip/sip_transaction.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com) |
3 | | * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org> |
4 | | * |
5 | | * This program is free software; you can redistribute it and/or modify |
6 | | * it under the terms of the GNU General Public License as published by |
7 | | * the Free Software Foundation; either version 2 of the License, or |
8 | | * (at your option) any later version. |
9 | | * |
10 | | * This program is distributed in the hope that it will be useful, |
11 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | | * GNU General Public License for more details. |
14 | | * |
15 | | * You should have received a copy of the GNU General Public License |
16 | | * along with this program; if not, write to the Free Software |
17 | | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
18 | | */ |
19 | | #include <pjsip/sip_transaction.h> |
20 | | #include <pjsip/sip_util.h> |
21 | | #include <pjsip/sip_module.h> |
22 | | #include <pjsip/sip_endpoint.h> |
23 | | #include <pjsip/sip_errno.h> |
24 | | #include <pjsip/sip_event.h> |
25 | | #include <pjlib-util/errno.h> |
26 | | #include <pj/hash.h> |
27 | | #include <pj/pool.h> |
28 | | #include <pj/os.h> |
29 | | #include <pj/rand.h> |
30 | | #include <pj/string.h> |
31 | | #include <pj/assert.h> |
32 | | #include <pj/guid.h> |
33 | | #include <pj/log.h> |
34 | | |
35 | | #define THIS_FILE "sip_transaction.c" |
36 | | |
37 | | #if 0 |
38 | | #define TSX_TRACE_(expr) PJ_LOG(3,expr) |
39 | | #else |
40 | | #define TSX_TRACE_(expr) |
41 | | #endif |
42 | | |
43 | | /* When this macro is set, transaction will keep the hashed value |
44 | | * so that future lookup (to unregister transaction) does not need |
45 | | * to recalculate the hash again. It should gains a little bit of |
46 | | * performance, so generally we'd want this. |
47 | | */ |
48 | | #define PRECALC_HASH |
49 | | |
50 | | |
51 | | /* Defined in sip_util_statefull.c */ |
52 | | extern pjsip_module mod_stateful_util; |
53 | | |
54 | | |
55 | | /***************************************************************************** |
56 | | ** |
57 | | ** Declarations and static variable definitions section. |
58 | | ** |
59 | | ***************************************************************************** |
60 | | **/ |
61 | | /* Prototypes. */ |
62 | | static pj_status_t mod_tsx_layer_load(pjsip_endpoint *endpt); |
63 | | static pj_status_t mod_tsx_layer_start(void); |
64 | | static pj_status_t mod_tsx_layer_stop(void); |
65 | | static pj_status_t mod_tsx_layer_unload(void); |
66 | | static pj_bool_t mod_tsx_layer_on_rx_request(pjsip_rx_data *rdata); |
67 | | static pj_bool_t mod_tsx_layer_on_rx_response(pjsip_rx_data *rdata); |
68 | | |
69 | | /* Transaction layer module definition. */ |
70 | | static struct mod_tsx_layer |
71 | | { |
72 | | struct pjsip_module mod; |
73 | | pj_pool_t *pool; |
74 | | pjsip_endpoint *endpt; |
75 | | pj_mutex_t *mutex; |
76 | | pj_hash_table_t *htable; |
77 | | pj_hash_table_t *htable2; |
78 | | } mod_tsx_layer = |
79 | | { { |
80 | | NULL, NULL, /* List's prev and next. */ |
81 | | { "mod-tsx-layer", 13 }, /* Module name. */ |
82 | | -1, /* Module ID */ |
83 | | PJSIP_MOD_PRIORITY_TSX_LAYER, /* Priority. */ |
84 | | mod_tsx_layer_load, /* load(). */ |
85 | | mod_tsx_layer_start, /* start() */ |
86 | | mod_tsx_layer_stop, /* stop() */ |
87 | | mod_tsx_layer_unload, /* unload() */ |
88 | | mod_tsx_layer_on_rx_request, /* on_rx_request() */ |
89 | | mod_tsx_layer_on_rx_response, /* on_rx_response() */ |
90 | | NULL |
91 | | } |
92 | | }; |
93 | | |
94 | | /* Transaction state names */ |
95 | | static const char *state_str[] = |
96 | | { |
97 | | "Null", |
98 | | "Calling", |
99 | | "Trying", |
100 | | "Proceeding", |
101 | | "Completed", |
102 | | "Confirmed", |
103 | | "Terminated", |
104 | | "Destroyed", |
105 | | }; |
106 | | |
107 | | /* Role names */ |
108 | | static const char *role_name[] = |
109 | | { |
110 | | "UAC", |
111 | | "UAS" |
112 | | }; |
113 | | |
114 | | /* Transport flag. */ |
115 | | enum |
116 | | { |
117 | | TSX_HAS_PENDING_TRANSPORT = 1, |
118 | | TSX_HAS_PENDING_RESCHED = 2, |
119 | | TSX_HAS_PENDING_SEND = 4, |
120 | | TSX_HAS_PENDING_DESTROY = 8, |
121 | | TSX_HAS_RESOLVED_SERVER = 16, |
122 | | }; |
123 | | |
124 | | /* Timer timeout value constants */ |
125 | | static pj_time_val t1_timer_val = { PJSIP_T1_TIMEOUT/1000, |
126 | | PJSIP_T1_TIMEOUT%1000 }; |
127 | | static pj_time_val t2_timer_val = { PJSIP_T2_TIMEOUT/1000, |
128 | | PJSIP_T2_TIMEOUT%1000 }; |
129 | | static pj_time_val t4_timer_val = { PJSIP_T4_TIMEOUT/1000, |
130 | | PJSIP_T4_TIMEOUT%1000 }; |
131 | | static pj_time_val td_timer_val = { PJSIP_TD_TIMEOUT/1000, |
132 | | PJSIP_TD_TIMEOUT%1000 }; |
133 | | static pj_time_val timeout_timer_val = { (64*PJSIP_T1_TIMEOUT)/1000, |
134 | | (64*PJSIP_T1_TIMEOUT)%1000 }; |
135 | | static int max_retrans_count = -1; |
136 | | |
137 | 0 | #define TIMER_INACTIVE 0 |
138 | 0 | #define RETRANSMIT_TIMER 1 |
139 | 0 | #define TIMEOUT_TIMER 2 |
140 | 0 | #define TRANSPORT_ERR_TIMER 3 |
141 | 0 | #define TRANSPORT_DISC_TIMER 4 |
142 | 0 | #define TERMINATE_TIMER 5 |
143 | 0 | #define TRANSPORT_CB_TIMER 6 |
144 | | |
145 | | /* Flags for tsx_set_state() */ |
146 | | enum |
147 | | { |
148 | | NO_NOTIFY = 1, |
149 | | NO_SCHEDULE_HANDLER = 2, |
150 | | RELEASE_LOCK = 4 |
151 | | }; |
152 | | |
153 | | /* Prototypes. */ |
154 | | static pj_status_t tsx_on_state_null( pjsip_transaction *tsx, |
155 | | pjsip_event *event); |
156 | | static pj_status_t tsx_on_state_calling( pjsip_transaction *tsx, |
157 | | pjsip_event *event); |
158 | | static pj_status_t tsx_on_state_trying( pjsip_transaction *tsx, |
159 | | pjsip_event *event); |
160 | | static pj_status_t tsx_on_state_proceeding_uas( pjsip_transaction *tsx, |
161 | | pjsip_event *event); |
162 | | static pj_status_t tsx_on_state_proceeding_uac( pjsip_transaction *tsx, |
163 | | pjsip_event *event); |
164 | | static pj_status_t tsx_on_state_completed_uas( pjsip_transaction *tsx, |
165 | | pjsip_event *event); |
166 | | static pj_status_t tsx_on_state_completed_uac( pjsip_transaction *tsx, |
167 | | pjsip_event *event); |
168 | | static pj_status_t tsx_on_state_confirmed( pjsip_transaction *tsx, |
169 | | pjsip_event *event); |
170 | | static pj_status_t tsx_on_state_terminated( pjsip_transaction *tsx, |
171 | | pjsip_event *event); |
172 | | static pj_status_t tsx_on_state_destroyed( pjsip_transaction *tsx, |
173 | | pjsip_event *event); |
174 | | static void tsx_timer_callback( pj_timer_heap_t *theap, |
175 | | pj_timer_entry *entry); |
176 | | static void tsx_tp_state_callback( |
177 | | pjsip_transport *tp, |
178 | | pjsip_transport_state state, |
179 | | const pjsip_transport_state_info *info); |
180 | | static void tsx_set_state( pjsip_transaction *tsx, |
181 | | pjsip_tsx_state_e state, |
182 | | pjsip_event_id_e event_src_type, |
183 | | void *event_src, |
184 | | int flag); |
185 | | static void tsx_set_status_code(pjsip_transaction *tsx, |
186 | | int code, const pj_str_t *reason); |
187 | | static pj_status_t tsx_create( pjsip_module *tsx_user, |
188 | | pj_grp_lock_t *grp_lock, |
189 | | pjsip_transaction **p_tsx); |
190 | | static void tsx_on_destroy(void *arg); |
191 | | static pj_status_t tsx_shutdown( pjsip_transaction *tsx ); |
192 | | static void tsx_resched_retransmission( pjsip_transaction *tsx ); |
193 | | static pj_status_t tsx_retransmit( pjsip_transaction *tsx, int resched); |
194 | | static int tsx_send_msg( pjsip_transaction *tsx, |
195 | | pjsip_tx_data *tdata); |
196 | | static void tsx_update_transport( pjsip_transaction *tsx, |
197 | | pjsip_transport *tp); |
198 | | |
199 | | |
200 | | /* State handlers for UAC, indexed by state */ |
201 | | static int (*tsx_state_handler_uac[PJSIP_TSX_STATE_MAX])(pjsip_transaction *, |
202 | | pjsip_event *) = |
203 | | { |
204 | | &tsx_on_state_null, |
205 | | &tsx_on_state_calling, |
206 | | NULL, |
207 | | &tsx_on_state_proceeding_uac, |
208 | | &tsx_on_state_completed_uac, |
209 | | &tsx_on_state_confirmed, |
210 | | &tsx_on_state_terminated, |
211 | | &tsx_on_state_destroyed, |
212 | | }; |
213 | | |
214 | | /* State handlers for UAS */ |
215 | | static int (*tsx_state_handler_uas[PJSIP_TSX_STATE_MAX])(pjsip_transaction *, |
216 | | pjsip_event *) = |
217 | | { |
218 | | &tsx_on_state_null, |
219 | | NULL, |
220 | | &tsx_on_state_trying, |
221 | | &tsx_on_state_proceeding_uas, |
222 | | &tsx_on_state_completed_uas, |
223 | | &tsx_on_state_confirmed, |
224 | | &tsx_on_state_terminated, |
225 | | &tsx_on_state_destroyed, |
226 | | }; |
227 | | |
228 | | /***************************************************************************** |
229 | | ** |
230 | | ** Utilities |
231 | | ** |
232 | | ***************************************************************************** |
233 | | */ |
234 | | /* |
235 | | * Get transaction state name. |
236 | | */ |
237 | | PJ_DEF(const char *) pjsip_tsx_state_str(pjsip_tsx_state_e state) |
238 | 0 | { |
239 | 0 | return state_str[state]; |
240 | 0 | } |
241 | | |
242 | | /* |
243 | | * Get the role name. |
244 | | */ |
245 | | PJ_DEF(const char *) pjsip_role_name(pjsip_role_e role) |
246 | 0 | { |
247 | 0 | return role_name[role]; |
248 | 0 | } |
249 | | |
250 | | |
251 | | /* |
252 | | * Create transaction key for RFC2543 compliant messages, which don't have |
253 | | * unique branch parameter in the top most Via header. |
254 | | * |
255 | | * INVITE requests matches a transaction if the following attributes |
256 | | * match the original request: |
257 | | * - Request-URI |
258 | | * - To tag |
259 | | * - From tag |
260 | | * - Call-ID |
261 | | * - CSeq |
262 | | * - top Via header |
263 | | * |
264 | | * CANCEL matching is done similarly as INVITE, except: |
265 | | * - CSeq method will differ |
266 | | * - To tag is not matched. |
267 | | * |
268 | | * ACK matching is done similarly, except that: |
269 | | * - method of the CSeq will differ, |
270 | | * - To tag is matched to the response sent by the server transaction. |
271 | | * |
272 | | * The transaction key is constructed from the common components of above |
273 | | * components. Additional comparison is needed to fully match a transaction. |
274 | | */ |
275 | | static pj_status_t create_tsx_key_2543( pj_pool_t *pool, |
276 | | pj_str_t *str, |
277 | | pjsip_role_e role, |
278 | | const pjsip_method *method, |
279 | | const pjsip_rx_data *rdata, |
280 | | pj_bool_t include_via ) |
281 | 0 | { |
282 | 0 | #define SEPARATOR '$' |
283 | 0 | char *key, *p; |
284 | 0 | pj_ssize_t len; |
285 | 0 | pj_size_t len_required; |
286 | 0 | pj_str_t *host; |
287 | |
|
288 | 0 | PJ_ASSERT_RETURN(pool && str && method && rdata, PJ_EINVAL); |
289 | 0 | PJ_ASSERT_RETURN(rdata->msg_info.msg, PJ_EINVAL); |
290 | 0 | PJ_ASSERT_RETURN(rdata->msg_info.via, PJSIP_EMISSINGHDR); |
291 | 0 | PJ_ASSERT_RETURN(rdata->msg_info.cseq, PJSIP_EMISSINGHDR); |
292 | 0 | PJ_ASSERT_RETURN(rdata->msg_info.from, PJSIP_EMISSINGHDR); |
293 | | |
294 | 0 | host = &rdata->msg_info.via->sent_by.host; |
295 | | |
296 | | /* Calculate length required. */ |
297 | 0 | len_required = method->name.slen + /* Method */ |
298 | 0 | 11 + /* CSeq number */ |
299 | 0 | rdata->msg_info.from->tag.slen + /* From tag. */ |
300 | 0 | rdata->msg_info.cid->id.slen + /* Call-ID */ |
301 | 0 | 16; /* Separator+Allowance. */ |
302 | 0 | if (include_via) { |
303 | 0 | len_required += host->slen + /* Via host. */ |
304 | 0 | 11; /* Via port. */ |
305 | 0 | } |
306 | 0 | key = p = (char*) pj_pool_alloc(pool, len_required); |
307 | | |
308 | | /* Add role. */ |
309 | 0 | *p++ = (char)(role==PJSIP_ROLE_UAC ? 'c' : 's'); |
310 | 0 | *p++ = SEPARATOR; |
311 | | |
312 | | /* Add method, except when method is INVITE or ACK. */ |
313 | 0 | if (method->id != PJSIP_INVITE_METHOD && method->id != PJSIP_ACK_METHOD) { |
314 | 0 | pj_memcpy(p, method->name.ptr, method->name.slen); |
315 | 0 | p += method->name.slen; |
316 | 0 | *p++ = '$'; |
317 | 0 | } |
318 | | |
319 | | /* Add CSeq (only the number). */ |
320 | 0 | len = pj_utoa(rdata->msg_info.cseq->cseq, p); |
321 | 0 | p += len; |
322 | 0 | *p++ = SEPARATOR; |
323 | | |
324 | | /* Add From tag. */ |
325 | 0 | len = rdata->msg_info.from->tag.slen; |
326 | 0 | pj_memcpy( p, rdata->msg_info.from->tag.ptr, len); |
327 | 0 | p += len; |
328 | 0 | *p++ = SEPARATOR; |
329 | | |
330 | | /* Add Call-ID. */ |
331 | 0 | len = rdata->msg_info.cid->id.slen; |
332 | 0 | pj_memcpy( p, rdata->msg_info.cid->id.ptr, len ); |
333 | 0 | p += len; |
334 | 0 | *p++ = SEPARATOR; |
335 | | |
336 | | /* Add top Via header. |
337 | | * We don't really care whether the port contains the real port (because |
338 | | * it can be omited if default port is used). Anyway this function is |
339 | | * only used to match request retransmission, and we expect that the |
340 | | * request retransmissions will contain the same port. |
341 | | */ |
342 | 0 | if (include_via) { |
343 | 0 | pj_memcpy(p, host->ptr, host->slen); |
344 | 0 | p += host->slen; |
345 | 0 | *p++ = ':'; |
346 | |
|
347 | 0 | len = pj_utoa(rdata->msg_info.via->sent_by.port, p); |
348 | 0 | p += len; |
349 | 0 | *p++ = SEPARATOR; |
350 | 0 | } |
351 | |
|
352 | 0 | *p++ = '\0'; |
353 | | |
354 | | /* Done. */ |
355 | 0 | str->ptr = key; |
356 | 0 | str->slen = p-key; |
357 | |
|
358 | 0 | return PJ_SUCCESS; |
359 | 0 | } |
360 | | |
361 | | /* |
362 | | * Create transaction key for RFC3161 compliant system. |
363 | | */ |
364 | | static pj_status_t create_tsx_key_3261( pj_pool_t *pool, |
365 | | pj_str_t *key, |
366 | | pjsip_role_e role, |
367 | | const pjsip_method *method, |
368 | | const pj_str_t *branch) |
369 | 0 | { |
370 | 0 | char *p; |
371 | |
|
372 | 0 | PJ_ASSERT_RETURN(pool && key && method && branch, PJ_EINVAL); |
373 | | |
374 | 0 | p = key->ptr = (char*) |
375 | 0 | pj_pool_alloc(pool, branch->slen + method->name.slen + 4 ); |
376 | | |
377 | | /* Add role. */ |
378 | 0 | *p++ = (char)(role==PJSIP_ROLE_UAC ? 'c' : 's'); |
379 | 0 | *p++ = SEPARATOR; |
380 | | |
381 | | /* Add method, except when method is INVITE or ACK. */ |
382 | 0 | if (method->id != PJSIP_INVITE_METHOD && method->id != PJSIP_ACK_METHOD) { |
383 | 0 | pj_memcpy(p, method->name.ptr, method->name.slen); |
384 | 0 | p += method->name.slen; |
385 | 0 | *p++ = '$'; |
386 | 0 | } |
387 | | |
388 | | /* Add branch ID. */ |
389 | 0 | pj_memcpy(p, branch->ptr, branch->slen); |
390 | 0 | p += branch->slen; |
391 | | |
392 | | /* Set length */ |
393 | 0 | key->slen = p - key->ptr; |
394 | |
|
395 | 0 | return PJ_SUCCESS; |
396 | 0 | } |
397 | | |
398 | | /* |
399 | | * Create key from the incoming data, to be used to search the transaction |
400 | | * in the transaction hash table. |
401 | | */ |
402 | | PJ_DEF(pj_status_t) pjsip_tsx_create_key( pj_pool_t *pool, pj_str_t *key, |
403 | | pjsip_role_e role, |
404 | | const pjsip_method *method, |
405 | | const pjsip_rx_data *rdata) |
406 | 0 | { |
407 | 0 | pj_str_t rfc3261_branch = {PJSIP_RFC3261_BRANCH_ID, |
408 | 0 | PJSIP_RFC3261_BRANCH_LEN}; |
409 | | |
410 | | |
411 | | /* Get the branch parameter in the top-most Via. |
412 | | * If branch parameter is started with "z9hG4bK", then the message was |
413 | | * generated by agent compliant with RFC3261. Otherwise, it will be |
414 | | * handled as RFC2543. |
415 | | */ |
416 | 0 | const pj_str_t *branch = &rdata->msg_info.via->branch_param; |
417 | |
|
418 | 0 | if (pj_strnicmp(branch,&rfc3261_branch,PJSIP_RFC3261_BRANCH_LEN)==0) { |
419 | | |
420 | | /* Create transaction key. */ |
421 | 0 | return create_tsx_key_3261(pool, key, role, method, branch); |
422 | |
|
423 | 0 | } else { |
424 | | /* Create the key for the message. This key will be matched up |
425 | | * with the transaction key. For RFC2563 transactions, the |
426 | | * transaction key was created by the same function, so it will |
427 | | * match the message. |
428 | | */ |
429 | 0 | return create_tsx_key_2543( pool, key, role, method, rdata, PJ_TRUE ); |
430 | 0 | } |
431 | 0 | } |
432 | | |
433 | | /* |
434 | | * Change timer values used by transaction layer. Currently scheduled |
435 | | * timers will not be changed. Any value set to 0 will be left |
436 | | * unchanged. |
437 | | * t1 - Transaction T1 timeout, in msec. Default value is PJSIP_T1_TIMEOUT |
438 | | * t2 - Transaction T2 timeout, in msec. Default value is PJSIP_T2_TIMEOUT |
439 | | * t4 - Transaction completed timer for non-INVITE, in msec. |
440 | | * Default value is PJSIP_T4_TIMEOUT |
441 | | * td - Transaction completed timer for INVITE, in msec. |
442 | | * Default value is PJSIP_TD_TIMEOUT |
443 | | */ |
444 | | PJ_DEF(void) pjsip_tsx_set_timers(unsigned t1, unsigned t2, unsigned t4, unsigned td) |
445 | 0 | { |
446 | 0 | if(t1!=0) { |
447 | 0 | t1_timer_val.sec = t1 / 1000; |
448 | 0 | t1_timer_val.msec = t1 % 1000; |
449 | 0 | pjsip_cfg()->tsx.t1=t1; |
450 | 0 | } |
451 | 0 | if(t2!=0) { |
452 | 0 | t2_timer_val.sec = t2 / 1000; |
453 | 0 | t2_timer_val.msec = t2 % 1000; |
454 | 0 | pjsip_cfg()->tsx.t2=t2; |
455 | 0 | } |
456 | 0 | if(t4!=0) { |
457 | 0 | t4_timer_val.sec = t4 / 1000; |
458 | 0 | t4_timer_val.msec = t4 % 1000; |
459 | 0 | pjsip_cfg()->tsx.t4=t4; |
460 | 0 | } |
461 | 0 | if(td!=0) { |
462 | 0 | td_timer_val.sec = td / 1000; |
463 | 0 | td_timer_val.msec = td % 1000; |
464 | 0 | timeout_timer_val = td_timer_val; |
465 | 0 | pjsip_cfg()->tsx.td=td; |
466 | 0 | } |
467 | 0 | } |
468 | | |
469 | | /* |
470 | | * (Re)Initializes timer values from `pjsip_cfg()`. |
471 | | */ |
472 | | PJ_DEF(void) pjsip_tsx_initialize_timer_values(void) |
473 | 5.06k | { |
474 | 5.06k | t1_timer_val.sec = pjsip_cfg()->tsx.t1 / 1000; |
475 | 5.06k | t1_timer_val.msec = pjsip_cfg()->tsx.t1 % 1000; |
476 | 5.06k | t2_timer_val.sec = pjsip_cfg()->tsx.t2 / 1000; |
477 | 5.06k | t2_timer_val.msec = pjsip_cfg()->tsx.t2 % 1000; |
478 | 5.06k | t4_timer_val.sec = pjsip_cfg()->tsx.t4 / 1000; |
479 | 5.06k | t4_timer_val.msec = pjsip_cfg()->tsx.t4 % 1000; |
480 | 5.06k | td_timer_val.sec = pjsip_cfg()->tsx.td / 1000; |
481 | 5.06k | td_timer_val.msec = pjsip_cfg()->tsx.td % 1000; |
482 | 5.06k | timeout_timer_val = td_timer_val; |
483 | 5.06k | } |
484 | | |
485 | | |
486 | | PJ_DEF(void) pjsip_tsx_set_max_retransmit_count(int max) |
487 | 0 | { |
488 | 0 | max_retrans_count = max; |
489 | 0 | } |
490 | | |
491 | | |
492 | | /***************************************************************************** |
493 | | ** |
494 | | ** Transaction layer module |
495 | | ** |
496 | | ***************************************************************************** |
497 | | **/ |
498 | | /* |
499 | | * Create transaction layer module and registers it to the endpoint. |
500 | | */ |
501 | | PJ_DEF(pj_status_t) pjsip_tsx_layer_init_module(pjsip_endpoint *endpt) |
502 | 5.06k | { |
503 | 5.06k | pj_pool_t *pool; |
504 | 5.06k | pj_status_t status; |
505 | | |
506 | | |
507 | 5.06k | PJ_ASSERT_RETURN(mod_tsx_layer.endpt==NULL, PJ_EINVALIDOP); |
508 | | |
509 | | /* Initialize timer values */ |
510 | 5.06k | pjsip_tsx_initialize_timer_values(); |
511 | | |
512 | | /* Reset max retrans count (for library restart scenario) */ |
513 | 5.06k | max_retrans_count = -1; |
514 | | |
515 | | /* |
516 | | * Initialize transaction layer structure. |
517 | | */ |
518 | | |
519 | | /* Create pool for the module. */ |
520 | 5.06k | pool = pjsip_endpt_create_pool(endpt, "tsxlayer", |
521 | 5.06k | PJSIP_POOL_TSX_LAYER_LEN, |
522 | 5.06k | PJSIP_POOL_TSX_LAYER_INC ); |
523 | 5.06k | if (!pool) |
524 | 0 | return PJ_ENOMEM; |
525 | | |
526 | | |
527 | | /* Initialize some attributes. */ |
528 | 5.06k | mod_tsx_layer.pool = pool; |
529 | 5.06k | mod_tsx_layer.endpt = endpt; |
530 | | |
531 | | |
532 | | /* Create hash table. */ |
533 | 5.06k | mod_tsx_layer.htable = pj_hash_create( pool, pjsip_cfg()->tsx.max_count ); |
534 | 5.06k | mod_tsx_layer.htable2 = pj_hash_create(pool, pjsip_cfg()->tsx.max_count); |
535 | 5.06k | if (!mod_tsx_layer.htable || !mod_tsx_layer.htable2) { |
536 | 0 | pjsip_endpt_release_pool(endpt, pool); |
537 | 0 | return PJ_ENOMEM; |
538 | 0 | } |
539 | | |
540 | | /* Create group lock. */ |
541 | 5.06k | status = pj_mutex_create_recursive(pool, "tsxlayer", &mod_tsx_layer.mutex); |
542 | 5.06k | if (status != PJ_SUCCESS) { |
543 | 0 | pjsip_endpt_release_pool(endpt, pool); |
544 | 0 | return status; |
545 | 0 | } |
546 | | |
547 | | /* |
548 | | * Register transaction layer module to endpoint. |
549 | | */ |
550 | 5.06k | status = pjsip_endpt_register_module( endpt, &mod_tsx_layer.mod ); |
551 | 5.06k | if (status != PJ_SUCCESS) { |
552 | 0 | pj_mutex_destroy(mod_tsx_layer.mutex); |
553 | 0 | pjsip_endpt_release_pool(endpt, pool); |
554 | 0 | return status; |
555 | 0 | } |
556 | | |
557 | | /* Register mod_stateful_util module (sip_util_statefull.c) */ |
558 | 5.06k | status = pjsip_endpt_register_module(endpt, &mod_stateful_util); |
559 | 5.06k | if (status != PJ_SUCCESS) { |
560 | 0 | return status; |
561 | 0 | } |
562 | | |
563 | 5.06k | return PJ_SUCCESS; |
564 | 5.06k | } |
565 | | |
566 | | |
567 | | /* |
568 | | * Get the instance of transaction layer module. |
569 | | */ |
570 | | PJ_DEF(pjsip_module*) pjsip_tsx_layer_instance(void) |
571 | 0 | { |
572 | 0 | return &mod_tsx_layer.mod; |
573 | 0 | } |
574 | | |
575 | | |
576 | | /* |
577 | | * Unregister and destroy transaction layer module. |
578 | | */ |
579 | | PJ_DEF(pj_status_t) pjsip_tsx_layer_destroy(void) |
580 | 0 | { |
581 | | /* Are we registered? */ |
582 | 0 | PJ_ASSERT_RETURN(mod_tsx_layer.endpt!=NULL, PJ_EINVALIDOP); |
583 | | |
584 | | /* Unregister from endpoint. |
585 | | * Clean-ups will be done in the unload() module callback. |
586 | | */ |
587 | 0 | return pjsip_endpt_unregister_module( mod_tsx_layer.endpt, |
588 | 0 | &mod_tsx_layer.mod); |
589 | 0 | } |
590 | | |
591 | | |
592 | | /* |
593 | | * Register the transaction to the hash table. |
594 | | */ |
595 | | static pj_status_t mod_tsx_layer_register_tsx( pjsip_transaction *tsx) |
596 | 0 | { |
597 | 0 | pj_assert(tsx->transaction_key.slen != 0); |
598 | | |
599 | | /* Lock hash table mutex. */ |
600 | 0 | pj_mutex_lock(mod_tsx_layer.mutex); |
601 | | |
602 | | /* Check if no transaction with the same key exists. |
603 | | * Do not use PJ_ASSERT_RETURN since it evaluates the expression |
604 | | * twice! |
605 | | */ |
606 | 0 | if(pj_hash_get_lower(mod_tsx_layer.htable, |
607 | 0 | tsx->transaction_key.ptr, |
608 | 0 | (unsigned)tsx->transaction_key.slen, |
609 | 0 | NULL)) |
610 | 0 | { |
611 | 0 | pj_mutex_unlock(mod_tsx_layer.mutex); |
612 | 0 | PJ_LOG(2,(THIS_FILE, |
613 | 0 | "Unable to register %.*s transaction (key exists)", |
614 | 0 | (int)tsx->method.name.slen, |
615 | 0 | tsx->method.name.ptr)); |
616 | 0 | return PJ_EEXISTS; |
617 | 0 | } |
618 | | |
619 | 0 | TSX_TRACE_((THIS_FILE, |
620 | 0 | "Transaction %p registered with hkey=0x%p and key=%.*s", |
621 | 0 | tsx, tsx->hashed_key, tsx->transaction_key.slen, |
622 | 0 | tsx->transaction_key.ptr)); |
623 | | |
624 | | /* Register the transaction to the hash tables. We register the tsx |
625 | | * to the secondary hash table only if it's UAS, for the purpose of |
626 | | * detecting merged requests. |
627 | | */ |
628 | 0 | #ifdef PRECALC_HASH |
629 | 0 | pj_hash_set_lower( tsx->pool, mod_tsx_layer.htable, |
630 | 0 | tsx->transaction_key.ptr, |
631 | 0 | (unsigned)tsx->transaction_key.slen, |
632 | 0 | tsx->hashed_key, tsx); |
633 | 0 | if (tsx->role == PJSIP_ROLE_UAS) { |
634 | 0 | pj_hash_set_lower( tsx->pool, mod_tsx_layer.htable2, |
635 | 0 | tsx->transaction_key2.ptr, |
636 | 0 | (unsigned)tsx->transaction_key2.slen, |
637 | 0 | tsx->hashed_key2, tsx); |
638 | 0 | } |
639 | | #else |
640 | | pj_hash_set_lower( tsx->pool, mod_tsx_layer.htable, |
641 | | tsx->transaction_key.ptr, |
642 | | tsx->transaction_key.slen, 0, tsx); |
643 | | if (tsx->role == PJSIP_ROLE_UAS) { |
644 | | pj_hash_set_lower( tsx->pool, mod_tsx_layer.htable2, |
645 | | tsx->transaction_key2.ptr, |
646 | | tsx->transaction_key2.slen, 0, tsx); |
647 | | } |
648 | | #endif |
649 | | |
650 | | /* Unlock mutex. */ |
651 | 0 | pj_mutex_unlock(mod_tsx_layer.mutex); |
652 | |
|
653 | 0 | return PJ_SUCCESS; |
654 | 0 | } |
655 | | |
656 | | |
657 | | /* |
658 | | * Unregister the transaction from the hash table. |
659 | | */ |
660 | | static void mod_tsx_layer_unregister_tsx( pjsip_transaction *tsx) |
661 | 0 | { |
662 | 0 | if (mod_tsx_layer.mod.id == -1) { |
663 | | /* The transaction layer has been unregistered. This could happen |
664 | | * if the transaction was pending on transport and the application |
665 | | * is shutdown. See https://github.com/pjsip/pjproject/issues/1033. In |
666 | | * this case just do nothing. |
667 | | */ |
668 | 0 | return; |
669 | 0 | } |
670 | | |
671 | 0 | pj_assert(tsx->transaction_key.slen != 0); |
672 | | //pj_assert(tsx->state != PJSIP_TSX_STATE_NULL); |
673 | | |
674 | | /* Lock hash table mutex. */ |
675 | 0 | pj_mutex_lock(mod_tsx_layer.mutex); |
676 | | |
677 | | /* Unregister the transaction from the hash tables. */ |
678 | 0 | #ifdef PRECALC_HASH |
679 | 0 | pj_hash_set_lower( NULL, mod_tsx_layer.htable, tsx->transaction_key.ptr, |
680 | 0 | (unsigned)tsx->transaction_key.slen, tsx->hashed_key, |
681 | 0 | NULL); |
682 | 0 | if (tsx->role == PJSIP_ROLE_UAS) { |
683 | 0 | pj_hash_set_lower(NULL, mod_tsx_layer.htable2, |
684 | 0 | tsx->transaction_key2.ptr, |
685 | 0 | (unsigned)tsx->transaction_key2.slen, |
686 | 0 | tsx->hashed_key2, NULL); |
687 | 0 | } |
688 | | #else |
689 | | pj_hash_set_lower( NULL, mod_tsx_layer.htable, tsx->transaction_key.ptr, |
690 | | tsx->transaction_key.slen, 0, NULL); |
691 | | if (tsx->role == PJSIP_ROLE_UAS) { |
692 | | pj_hash_set_lower(NULL, mod_tsx_layer.htable2, |
693 | | tsx->transaction_key2.ptr, |
694 | | tsx->transaction_key2.slen, 0, NULL); |
695 | | } |
696 | | #endif |
697 | |
|
698 | 0 | TSX_TRACE_((THIS_FILE, |
699 | 0 | "Transaction %p unregistered, hkey=0x%p and key=%.*s", |
700 | 0 | tsx, tsx->hashed_key, tsx->transaction_key.slen, |
701 | 0 | tsx->transaction_key.ptr)); |
702 | | |
703 | | /* Unlock mutex. */ |
704 | 0 | pj_mutex_unlock(mod_tsx_layer.mutex); |
705 | 0 | } |
706 | | |
707 | | |
708 | | /* |
709 | | * Retrieve the current number of transactions currently registered in |
710 | | * the hash table. |
711 | | */ |
712 | | PJ_DEF(unsigned) pjsip_tsx_layer_get_tsx_count(void) |
713 | 0 | { |
714 | 0 | unsigned count; |
715 | | |
716 | | /* Are we registered? */ |
717 | 0 | PJ_ASSERT_RETURN(mod_tsx_layer.endpt!=NULL, 0); |
718 | | |
719 | 0 | pj_mutex_lock(mod_tsx_layer.mutex); |
720 | 0 | count = pj_hash_count(mod_tsx_layer.htable); |
721 | 0 | pj_mutex_unlock(mod_tsx_layer.mutex); |
722 | |
|
723 | 0 | return count; |
724 | 0 | } |
725 | | |
726 | | |
727 | | /* |
728 | | * Find a transaction. |
729 | | */ |
730 | | static pjsip_transaction* find_tsx( const pj_str_t *key, pj_bool_t lock, |
731 | | pj_bool_t add_ref ) |
732 | 0 | { |
733 | 0 | pjsip_transaction *tsx; |
734 | 0 | pj_uint32_t hval = 0; |
735 | |
|
736 | 0 | pj_mutex_lock(mod_tsx_layer.mutex); |
737 | 0 | tsx = (pjsip_transaction*) |
738 | 0 | pj_hash_get_lower( mod_tsx_layer.htable, key->ptr, |
739 | 0 | (unsigned)key->slen, &hval ); |
740 | | |
741 | | /* Prevent the transaction to get deleted before we have chance to lock it. |
742 | | */ |
743 | 0 | if (tsx) |
744 | 0 | pj_grp_lock_add_ref(tsx->grp_lock); |
745 | | |
746 | 0 | pj_mutex_unlock(mod_tsx_layer.mutex); |
747 | |
|
748 | 0 | TSX_TRACE_((THIS_FILE, |
749 | 0 | "Finding tsx with hkey=0x%p and key=%.*s: found %p", |
750 | 0 | hval, key->slen, key->ptr, tsx)); |
751 | | |
752 | | /* Simulate race condition! */ |
753 | 0 | PJ_RACE_ME(5); |
754 | |
|
755 | 0 | if (tsx) { |
756 | 0 | if (lock) |
757 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
758 | |
|
759 | 0 | if (!add_ref) |
760 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
761 | 0 | } |
762 | |
|
763 | 0 | return tsx; |
764 | 0 | } |
765 | | |
766 | | |
767 | | PJ_DEF(pjsip_transaction*) pjsip_tsx_layer_find_tsx( const pj_str_t *key, |
768 | | pj_bool_t lock ) |
769 | 0 | { |
770 | 0 | return find_tsx(key, lock, PJ_FALSE); |
771 | 0 | } |
772 | | |
773 | | |
774 | | PJ_DEF(pjsip_transaction*) pjsip_tsx_layer_find_tsx2( const pj_str_t *key, |
775 | | pj_bool_t add_ref ) |
776 | 0 | { |
777 | 0 | return find_tsx(key, PJ_FALSE, add_ref); |
778 | 0 | } |
779 | | |
780 | | |
781 | | /* This module callback is called when module is being loaded by |
782 | | * endpoint. It does nothing for this module. |
783 | | */ |
784 | | static pj_status_t mod_tsx_layer_load(pjsip_endpoint *endpt) |
785 | 5.06k | { |
786 | 5.06k | PJ_UNUSED_ARG(endpt); |
787 | 5.06k | return PJ_SUCCESS; |
788 | 5.06k | } |
789 | | |
790 | | |
791 | | /* This module callback is called when module is being started by |
792 | | * endpoint. It does nothing for this module. |
793 | | */ |
794 | | static pj_status_t mod_tsx_layer_start(void) |
795 | 5.06k | { |
796 | 5.06k | return PJ_SUCCESS; |
797 | 5.06k | } |
798 | | |
799 | | |
800 | | /* This module callback is called when module is being stopped by |
801 | | * endpoint. |
802 | | */ |
803 | | static pj_status_t mod_tsx_layer_stop(void) |
804 | 5.06k | { |
805 | 5.06k | pj_hash_iterator_t it_buf, *it; |
806 | | |
807 | 5.06k | PJ_LOG(4,(THIS_FILE, "Stopping transaction layer module")); |
808 | | |
809 | 5.06k | pj_mutex_lock(mod_tsx_layer.mutex); |
810 | | |
811 | | /* Destroy all transactions. */ |
812 | 5.06k | it = pj_hash_first(mod_tsx_layer.htable, &it_buf); |
813 | 5.06k | while (it) { |
814 | 0 | pjsip_transaction *tsx = (pjsip_transaction*) |
815 | 0 | pj_hash_this(mod_tsx_layer.htable, it); |
816 | 0 | pj_hash_iterator_t *next = pj_hash_next(mod_tsx_layer.htable, it); |
817 | 0 | if (tsx) { |
818 | 0 | pjsip_tsx_terminate(tsx, PJSIP_SC_SERVICE_UNAVAILABLE); |
819 | 0 | mod_tsx_layer_unregister_tsx(tsx); |
820 | 0 | tsx_shutdown(tsx); |
821 | 0 | } |
822 | 0 | it = next; |
823 | 0 | } |
824 | | |
825 | 5.06k | pj_mutex_unlock(mod_tsx_layer.mutex); |
826 | | |
827 | 5.06k | PJ_LOG(4,(THIS_FILE, "Stopped transaction layer module")); |
828 | | |
829 | 5.06k | return PJ_SUCCESS; |
830 | 5.06k | } |
831 | | |
832 | | |
833 | | /* Destroy this module */ |
834 | | static void tsx_layer_destroy(pjsip_endpoint *endpt) |
835 | 5.06k | { |
836 | 5.06k | PJ_UNUSED_ARG(endpt); |
837 | | |
838 | | /* Destroy mutex. */ |
839 | 5.06k | pj_mutex_destroy(mod_tsx_layer.mutex); |
840 | | |
841 | | /* Release pool. */ |
842 | 5.06k | pjsip_endpt_release_pool(mod_tsx_layer.endpt, mod_tsx_layer.pool); |
843 | | |
844 | | /* Mark as unregistered. */ |
845 | 5.06k | mod_tsx_layer.endpt = NULL; |
846 | | |
847 | 5.06k | PJ_LOG(4,(THIS_FILE, "Transaction layer module destroyed")); |
848 | 5.06k | } |
849 | | |
850 | | |
851 | | /* This module callback is called when module is being unloaded by |
852 | | * endpoint. |
853 | | */ |
854 | | static pj_status_t mod_tsx_layer_unload(void) |
855 | 5.06k | { |
856 | | /* Only self destroy when there's no transaction in the table. |
857 | | * Transaction may refuse to destroy when it has pending |
858 | | * transmission. If we destroy the module now, application will |
859 | | * crash when the pending transaction finally got error response |
860 | | * from transport and when it tries to unregister itself. |
861 | | */ |
862 | 5.06k | if (pj_hash_count(mod_tsx_layer.htable) != 0) { |
863 | 0 | pj_status_t status; |
864 | 0 | status = pjsip_endpt_atexit(mod_tsx_layer.endpt, &tsx_layer_destroy); |
865 | 0 | if (status != PJ_SUCCESS) { |
866 | 0 | PJ_PERROR(3,(THIS_FILE, status, |
867 | 0 | "Failed to register transaction layer module destroy.")); |
868 | 0 | } |
869 | 0 | return PJ_EBUSY; |
870 | 0 | } |
871 | | |
872 | 5.06k | tsx_layer_destroy(mod_tsx_layer.endpt); |
873 | | |
874 | 5.06k | return PJ_SUCCESS; |
875 | 5.06k | } |
876 | | |
877 | | |
878 | | /* Detect merged requests as per RFC 3261 section 8.2.2.2. */ |
879 | | PJ_DEF(pjsip_transaction *) |
880 | | pjsip_tsx_detect_merged_requests(pjsip_rx_data *rdata) |
881 | 0 | { |
882 | 0 | pj_str_t key, key2; |
883 | 0 | pj_uint32_t hval = 0; |
884 | 0 | pjsip_transaction *tsx = NULL; |
885 | 0 | pj_status_t status; |
886 | |
|
887 | 0 | PJ_ASSERT_RETURN(rdata->msg_info.msg->type == PJSIP_REQUEST_MSG, NULL); |
888 | | |
889 | | /* If the request has no tag in the To header field, the UAS core MUST |
890 | | * check the request against ongoing transactions. |
891 | | */ |
892 | 0 | if (rdata->msg_info.to->tag.slen != 0) |
893 | 0 | return NULL; |
894 | | |
895 | 0 | status = pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAS, |
896 | 0 | &rdata->msg_info.cseq->method, rdata); |
897 | 0 | if (status != PJ_SUCCESS) |
898 | 0 | return NULL; |
899 | | |
900 | 0 | pj_mutex_lock( mod_tsx_layer.mutex ); |
901 | | |
902 | | /* This request must not match any transaction in our primary hash |
903 | | * table. |
904 | | */ |
905 | 0 | if (pj_hash_get_lower(mod_tsx_layer.htable, key.ptr, (unsigned)key.slen, |
906 | 0 | &hval) != NULL) |
907 | 0 | { |
908 | 0 | pj_mutex_unlock( mod_tsx_layer.mutex); |
909 | 0 | return NULL; |
910 | 0 | } |
911 | | |
912 | | /* Now check it against our secondary hash table, based on a key that |
913 | | * consists of From tag, CSeq, and Call-ID. |
914 | | */ |
915 | 0 | status = create_tsx_key_2543(rdata->tp_info.pool, &key2, PJSIP_ROLE_UAS, |
916 | 0 | &rdata->msg_info.cseq->method, rdata, |
917 | 0 | PJ_FALSE); |
918 | 0 | if (status != PJ_SUCCESS) { |
919 | 0 | pj_mutex_unlock( mod_tsx_layer.mutex); |
920 | 0 | return NULL; |
921 | 0 | } |
922 | | |
923 | 0 | hval = 0; |
924 | 0 | tsx = pj_hash_get_lower(mod_tsx_layer.htable2, key2.ptr, |
925 | 0 | (unsigned)key2.slen, &hval); |
926 | |
|
927 | 0 | pj_mutex_unlock( mod_tsx_layer.mutex); |
928 | |
|
929 | 0 | return tsx; |
930 | 0 | } |
931 | | |
932 | | /* This module callback is called when endpoint has received an |
933 | | * incoming request message. |
934 | | */ |
935 | | static pj_bool_t mod_tsx_layer_on_rx_request(pjsip_rx_data *rdata) |
936 | 0 | { |
937 | 0 | pj_str_t key; |
938 | 0 | pj_uint32_t hval = 0; |
939 | 0 | pjsip_transaction *tsx; |
940 | |
|
941 | 0 | pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAS, |
942 | 0 | &rdata->msg_info.cseq->method, rdata); |
943 | | |
944 | | /* Find transaction. */ |
945 | 0 | pj_mutex_lock( mod_tsx_layer.mutex ); |
946 | |
|
947 | 0 | tsx = (pjsip_transaction*) |
948 | 0 | pj_hash_get_lower( mod_tsx_layer.htable, key.ptr, (unsigned)key.slen, |
949 | 0 | &hval ); |
950 | | |
951 | |
|
952 | 0 | TSX_TRACE_((THIS_FILE, |
953 | 0 | "Finding tsx for request, hkey=0x%p and key=%.*s, found %p", |
954 | 0 | hval, key.slen, key.ptr, tsx)); |
955 | | |
956 | |
|
957 | 0 | if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { |
958 | | /* Transaction not found. |
959 | | * Reject the request so that endpoint passes the request to |
960 | | * upper layer modules. |
961 | | */ |
962 | 0 | pj_mutex_unlock( mod_tsx_layer.mutex); |
963 | 0 | return PJ_FALSE; |
964 | 0 | } |
965 | | |
966 | | /* In the case of an INVITE transaction, if the response was a 2xx, |
967 | | * the ACK is not considered part of the transaction. |
968 | | * Let sip_dialog and sip_inv handle it instead. |
969 | | */ |
970 | 0 | if (rdata->msg_info.msg->line.req.method.id == PJSIP_ACK_METHOD && |
971 | 0 | tsx->method.id == PJSIP_INVITE_METHOD && |
972 | 0 | tsx->status_code/100 == 2) |
973 | 0 | { |
974 | 0 | pj_mutex_unlock( mod_tsx_layer.mutex); |
975 | 0 | return PJ_FALSE; |
976 | 0 | } |
977 | | |
978 | | /* Prevent the transaction to get deleted before we have chance to lock it |
979 | | * in pjsip_tsx_recv_msg(). |
980 | | */ |
981 | 0 | pj_grp_lock_add_ref(tsx->grp_lock); |
982 | | |
983 | | /* Unlock hash table. */ |
984 | 0 | pj_mutex_unlock( mod_tsx_layer.mutex ); |
985 | | |
986 | | /* Simulate race condition! */ |
987 | 0 | PJ_RACE_ME(5); |
988 | | |
989 | | /* Pass the message to the transaction. */ |
990 | 0 | pjsip_tsx_recv_msg(tsx, rdata ); |
991 | | |
992 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
993 | |
|
994 | 0 | return PJ_TRUE; |
995 | 0 | } |
996 | | |
997 | | |
998 | | /* This module callback is called when endpoint has received an |
999 | | * incoming response message. |
1000 | | */ |
1001 | | static pj_bool_t mod_tsx_layer_on_rx_response(pjsip_rx_data *rdata) |
1002 | 0 | { |
1003 | 0 | pj_str_t key; |
1004 | 0 | pj_uint32_t hval = 0; |
1005 | 0 | pjsip_transaction *tsx; |
1006 | |
|
1007 | 0 | pjsip_tsx_create_key(rdata->tp_info.pool, &key, PJSIP_ROLE_UAC, |
1008 | 0 | &rdata->msg_info.cseq->method, rdata); |
1009 | | |
1010 | | /* Find transaction. */ |
1011 | 0 | pj_mutex_lock( mod_tsx_layer.mutex ); |
1012 | |
|
1013 | 0 | tsx = (pjsip_transaction*) |
1014 | 0 | pj_hash_get_lower( mod_tsx_layer.htable, key.ptr, (unsigned)key.slen, |
1015 | 0 | &hval ); |
1016 | | |
1017 | |
|
1018 | 0 | TSX_TRACE_((THIS_FILE, |
1019 | 0 | "Finding tsx for response, hkey=0x%p and key=%.*s, found %p", |
1020 | 0 | hval, key.slen, key.ptr, tsx)); |
1021 | | |
1022 | |
|
1023 | 0 | if (tsx == NULL || tsx->state == PJSIP_TSX_STATE_TERMINATED) { |
1024 | | /* Transaction not found. |
1025 | | * Reject the request so that endpoint passes the request to |
1026 | | * upper layer modules. |
1027 | | */ |
1028 | 0 | pj_mutex_unlock( mod_tsx_layer.mutex); |
1029 | 0 | return PJ_FALSE; |
1030 | 0 | } |
1031 | | |
1032 | | /* Prevent the transaction to get deleted before we have chance to lock it |
1033 | | * in pjsip_tsx_recv_msg(). |
1034 | | */ |
1035 | 0 | pj_grp_lock_add_ref(tsx->grp_lock); |
1036 | | |
1037 | | /* Unlock hash table. */ |
1038 | 0 | pj_mutex_unlock( mod_tsx_layer.mutex ); |
1039 | | |
1040 | | /* Simulate race condition! */ |
1041 | 0 | PJ_RACE_ME(5); |
1042 | | |
1043 | | /* Pass the message to the transaction. */ |
1044 | 0 | pjsip_tsx_recv_msg(tsx, rdata ); |
1045 | | |
1046 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
1047 | |
|
1048 | 0 | return PJ_TRUE; |
1049 | 0 | } |
1050 | | |
1051 | | |
1052 | | /* |
1053 | | * Get transaction instance in the rdata. |
1054 | | */ |
1055 | | PJ_DEF(pjsip_transaction*) pjsip_rdata_get_tsx( pjsip_rx_data *rdata ) |
1056 | 0 | { |
1057 | 0 | return (pjsip_transaction*) |
1058 | 0 | rdata->endpt_info.mod_data[mod_tsx_layer.mod.id]; |
1059 | 0 | } |
1060 | | |
1061 | | |
1062 | | /* |
1063 | | * Dump transaction layer. |
1064 | | */ |
1065 | | PJ_DEF(void) pjsip_tsx_layer_dump(pj_bool_t detail) |
1066 | 0 | { |
1067 | 0 | #if PJ_LOG_MAX_LEVEL >= 3 |
1068 | 0 | pj_hash_iterator_t itbuf, *it; |
1069 | | |
1070 | | /* Lock mutex. */ |
1071 | 0 | pj_mutex_lock(mod_tsx_layer.mutex); |
1072 | |
|
1073 | 0 | PJ_LOG(3, (THIS_FILE, "Dumping transaction table:")); |
1074 | 0 | PJ_LOG(3, (THIS_FILE, " Total %d transactions", |
1075 | 0 | pj_hash_count(mod_tsx_layer.htable))); |
1076 | |
|
1077 | 0 | if (detail) { |
1078 | 0 | it = pj_hash_first(mod_tsx_layer.htable, &itbuf); |
1079 | 0 | if (it == NULL) { |
1080 | 0 | PJ_LOG(3, (THIS_FILE, " - none - ")); |
1081 | 0 | } else { |
1082 | 0 | while (it != NULL) { |
1083 | 0 | pjsip_transaction *tsx = (pjsip_transaction*) |
1084 | 0 | pj_hash_this(mod_tsx_layer.htable,it); |
1085 | |
|
1086 | 0 | PJ_LOG(3, (THIS_FILE, " %s %s|%d|%s", |
1087 | 0 | tsx->obj_name, |
1088 | 0 | (tsx->last_tx? |
1089 | 0 | pjsip_tx_data_get_info(tsx->last_tx): |
1090 | 0 | "none"), |
1091 | 0 | tsx->status_code, |
1092 | 0 | pjsip_tsx_state_str(tsx->state))); |
1093 | |
|
1094 | 0 | it = pj_hash_next(mod_tsx_layer.htable, it); |
1095 | 0 | } |
1096 | 0 | } |
1097 | 0 | } |
1098 | | |
1099 | | /* Unlock mutex. */ |
1100 | 0 | pj_mutex_unlock(mod_tsx_layer.mutex); |
1101 | 0 | #endif |
1102 | 0 | } |
1103 | | |
1104 | | /***************************************************************************** |
1105 | | ** |
1106 | | ** Transaction |
1107 | | ** |
1108 | | ***************************************************************************** |
1109 | | **/ |
1110 | | /* Lock transaction for accessing the timeout timer only. */ |
1111 | | static void lock_timer(pjsip_transaction *tsx) |
1112 | 0 | { |
1113 | 0 | pj_mutex_lock(tsx->mutex_b); |
1114 | 0 | } |
1115 | | |
1116 | | /* Unlock timer */ |
1117 | | static void unlock_timer(pjsip_transaction *tsx) |
1118 | 0 | { |
1119 | 0 | pj_mutex_unlock(tsx->mutex_b); |
1120 | 0 | } |
1121 | | |
1122 | | /* Utility: schedule a timer */ |
1123 | | static pj_status_t tsx_schedule_timer(pjsip_transaction *tsx, |
1124 | | pj_timer_entry *entry, |
1125 | | const pj_time_val *delay, |
1126 | | int active_id) |
1127 | 0 | { |
1128 | 0 | pj_timer_heap_t *timer_heap = pjsip_endpt_get_timer_heap(tsx->endpt); |
1129 | 0 | pj_status_t status; |
1130 | |
|
1131 | 0 | pj_assert(active_id != 0); |
1132 | 0 | status = pj_timer_heap_schedule_w_grp_lock(timer_heap, entry, |
1133 | 0 | delay, active_id, |
1134 | 0 | tsx->grp_lock); |
1135 | |
|
1136 | 0 | return status; |
1137 | 0 | } |
1138 | | |
1139 | | /* Utility: cancel a timer */ |
1140 | | static int tsx_cancel_timer(pjsip_transaction *tsx, |
1141 | | pj_timer_entry *entry) |
1142 | 0 | { |
1143 | 0 | pj_timer_heap_t *timer_heap = pjsip_endpt_get_timer_heap(tsx->endpt); |
1144 | 0 | return pj_timer_heap_cancel_if_active(timer_heap, entry, TIMER_INACTIVE); |
1145 | 0 | } |
1146 | | |
1147 | | /* Create and initialize basic transaction structure. |
1148 | | * This function is called by both UAC and UAS creation. |
1149 | | */ |
1150 | | static pj_status_t tsx_create( pjsip_module *tsx_user, |
1151 | | pj_grp_lock_t *grp_lock, |
1152 | | pjsip_transaction **p_tsx) |
1153 | 0 | { |
1154 | 0 | pj_pool_t *pool; |
1155 | 0 | pjsip_transaction *tsx; |
1156 | 0 | pj_status_t status; |
1157 | |
|
1158 | 0 | pool = pjsip_endpt_create_pool( mod_tsx_layer.endpt, "tsx", |
1159 | 0 | PJSIP_POOL_TSX_LEN, PJSIP_POOL_TSX_INC ); |
1160 | 0 | if (!pool) |
1161 | 0 | return PJ_ENOMEM; |
1162 | | |
1163 | 0 | tsx = PJ_POOL_ZALLOC_T(pool, pjsip_transaction); |
1164 | 0 | tsx->pool = pool; |
1165 | 0 | tsx->tsx_user = tsx_user; |
1166 | 0 | tsx->endpt = mod_tsx_layer.endpt; |
1167 | |
|
1168 | 0 | pj_ansi_snprintf(tsx->obj_name, sizeof(tsx->obj_name), |
1169 | 0 | "tsx%p", tsx); |
1170 | 0 | pj_memcpy(pool->obj_name, tsx->obj_name, sizeof(pool->obj_name)); |
1171 | |
|
1172 | 0 | tsx->handle_200resp = 1; |
1173 | 0 | tsx->retransmit_timer.id = TIMER_INACTIVE; |
1174 | 0 | tsx->retransmit_timer.user_data = tsx; |
1175 | 0 | tsx->retransmit_timer.cb = &tsx_timer_callback; |
1176 | 0 | tsx->timeout_timer.id = TIMER_INACTIVE; |
1177 | 0 | tsx->timeout_timer.user_data = tsx; |
1178 | 0 | tsx->timeout_timer.cb = &tsx_timer_callback; |
1179 | | |
1180 | 0 | if (grp_lock) { |
1181 | 0 | tsx->grp_lock = grp_lock; |
1182 | | |
1183 | 0 | pj_grp_lock_add_ref(tsx->grp_lock); |
1184 | 0 | pj_grp_lock_add_handler(tsx->grp_lock, tsx->pool, tsx, &tsx_on_destroy); |
1185 | 0 | } else { |
1186 | 0 | status = pj_grp_lock_create_w_handler(pool, NULL, tsx, &tsx_on_destroy, |
1187 | 0 | &tsx->grp_lock); |
1188 | 0 | if (status != PJ_SUCCESS) { |
1189 | 0 | pjsip_endpt_release_pool(mod_tsx_layer.endpt, pool); |
1190 | 0 | return status; |
1191 | 0 | } |
1192 | | |
1193 | 0 | pj_grp_lock_add_ref(tsx->grp_lock); |
1194 | 0 | } |
1195 | | |
1196 | 0 | status = pj_mutex_create_simple(pool, tsx->obj_name, &tsx->mutex_b); |
1197 | 0 | if (status != PJ_SUCCESS) { |
1198 | 0 | tsx_shutdown(tsx); |
1199 | 0 | return status; |
1200 | 0 | } |
1201 | | |
1202 | 0 | *p_tsx = tsx; |
1203 | 0 | return PJ_SUCCESS; |
1204 | 0 | } |
1205 | | |
1206 | | /* Really destroy transaction, when grp_lock reference is zero */ |
1207 | | static void tsx_on_destroy( void *arg ) |
1208 | 0 | { |
1209 | 0 | pjsip_transaction *tsx = (pjsip_transaction*)arg; |
1210 | |
|
1211 | 0 | PJ_LOG(5,(tsx->obj_name, "Transaction destroyed!")); |
1212 | |
|
1213 | 0 | pj_mutex_destroy(tsx->mutex_b); |
1214 | 0 | pjsip_endpt_release_pool(tsx->endpt, tsx->pool); |
1215 | 0 | } |
1216 | | |
1217 | | /* Shutdown transaction. */ |
1218 | | static pj_status_t tsx_shutdown( pjsip_transaction *tsx ) |
1219 | 0 | { |
1220 | | /* Release the transport */ |
1221 | 0 | tsx_update_transport(tsx, NULL); |
1222 | | |
1223 | | /* Decrement reference counter in transport selector, only if |
1224 | | * we haven't been called before */ |
1225 | 0 | if (!tsx->terminating) { |
1226 | 0 | pjsip_tpselector_dec_ref(&tsx->tp_sel); |
1227 | 0 | } |
1228 | | |
1229 | | /* Free last transmitted message. */ |
1230 | 0 | if (tsx->last_tx) { |
1231 | 0 | pjsip_tx_data_dec_ref( tsx->last_tx ); |
1232 | 0 | tsx->last_tx = NULL; |
1233 | 0 | } |
1234 | | /* Cancel timeout timer. */ |
1235 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
1236 | | |
1237 | | /* Cancel retransmission timer. */ |
1238 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
1239 | | |
1240 | | /* Clear some pending flags. */ |
1241 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED | TSX_HAS_PENDING_SEND); |
1242 | | |
1243 | | |
1244 | | /* Refuse to destroy transaction if it has pending resolving. */ |
1245 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { |
1246 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_DESTROY; |
1247 | 0 | tsx->tsx_user = NULL; |
1248 | 0 | PJ_LOG(4,(tsx->obj_name, "Will destroy later because transport is " |
1249 | 0 | "in progress")); |
1250 | 0 | } |
1251 | |
|
1252 | 0 | if (!tsx->terminating) { |
1253 | 0 | tsx->terminating = PJ_TRUE; |
1254 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
1255 | 0 | } |
1256 | | |
1257 | | /* No acccess to tsx after this, it may have been destroyed */ |
1258 | |
|
1259 | 0 | return PJ_SUCCESS; |
1260 | 0 | } |
1261 | | |
1262 | | |
1263 | | /* |
1264 | | * Callback when timer expires. Transport error also piggybacks this event |
1265 | | * to avoid deadlock (https://github.com/pjsip/pjproject/issues/1646). |
1266 | | */ |
1267 | | static void tsx_timer_callback( pj_timer_heap_t *theap, pj_timer_entry *entry) |
1268 | 0 | { |
1269 | 0 | pjsip_transaction *tsx = (pjsip_transaction*) entry->user_data; |
1270 | |
|
1271 | 0 | PJ_UNUSED_ARG(theap); |
1272 | | |
1273 | | /* Just return if transaction is already destroyed (see also #2102). */ |
1274 | 0 | if (tsx->state >= PJSIP_TSX_STATE_DESTROYED) { |
1275 | 0 | return; |
1276 | 0 | } |
1277 | | |
1278 | | |
1279 | 0 | if (entry->id == TERMINATE_TIMER) { |
1280 | 0 | if (tsx->state < PJSIP_TSX_STATE_TERMINATED) { |
1281 | 0 | pjsip_tsx_terminate(tsx, tsx->status_code); |
1282 | 0 | } |
1283 | 0 | } else if (entry->id == TRANSPORT_ERR_TIMER || |
1284 | 0 | entry->id == TRANSPORT_DISC_TIMER) |
1285 | 0 | { |
1286 | | /* Posted transport error/disconnection event */ |
1287 | 0 | pj_bool_t tp_disc = (entry->id == TRANSPORT_DISC_TIMER); |
1288 | |
|
1289 | 0 | entry->id = 0; |
1290 | 0 | if (tsx->state < PJSIP_TSX_STATE_TERMINATED) { |
1291 | 0 | pjsip_tsx_state_e prev_state; |
1292 | 0 | pj_time_val timeout = { 0, 0 }; |
1293 | |
|
1294 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
1295 | 0 | prev_state = tsx->state; |
1296 | | |
1297 | | /* Release transport as it's no longer working. */ |
1298 | 0 | tsx_update_transport(tsx, NULL); |
1299 | |
|
1300 | 0 | #if PJSIP_TSX_UAS_CONTINUE_ON_TP_ERROR |
1301 | 0 | if (tp_disc && tsx->method.id == PJSIP_INVITE_METHOD && |
1302 | 0 | tsx->role == PJSIP_ROLE_UAS && tsx->status_code < 200 && |
1303 | 0 | !(tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) && |
1304 | 0 | !(tsx->transport_flag & TSX_HAS_PENDING_DESTROY)) |
1305 | | #else |
1306 | | PJ_UNUSED_ARG(tp_disc); |
1307 | | if (0) |
1308 | | #endif |
1309 | 0 | { |
1310 | | /* Upon transport disconnection event, if we receive |
1311 | | * incoming INVITE and haven't responded with a final answer, |
1312 | | * just return here and don't terminate the transaction, |
1313 | | * in case that the library can switch to another working |
1314 | | * transport. |
1315 | | */ |
1316 | 0 | tsx->transport_flag = 0; |
1317 | 0 | tsx->addr_len = 0; |
1318 | 0 | tsx->res_addr.transport = NULL; |
1319 | 0 | tsx->res_addr.addr_len = 0; |
1320 | | |
1321 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1322 | 0 | return; |
1323 | 0 | } |
1324 | | |
1325 | 0 | if (tsx->status_code < 200) { |
1326 | 0 | pj_str_t err; |
1327 | 0 | char errmsg[PJ_ERR_MSG_SIZE]; |
1328 | |
|
1329 | 0 | err = pj_strerror(tsx->transport_err, errmsg, sizeof(errmsg)); |
1330 | 0 | tsx_set_status_code(tsx, PJSIP_SC_TSX_TRANSPORT_ERROR, &err); |
1331 | 0 | } |
1332 | | |
1333 | | /* Set transaction state etc, but don't notify TU now, |
1334 | | * otherwise we'll get a deadlock. See: |
1335 | | * https://github.com/pjsip/pjproject/issues/1646 |
1336 | | */ |
1337 | | /* Also don't schedule tsx handler, otherwise we'll get race |
1338 | | * condition of TU notifications due to delayed TERMINATED |
1339 | | * state TU notification. It happened in multiple worker threads |
1340 | | * environment between TERMINATED & DESTROYED! See: |
1341 | | * https://github.com/pjsip/pjproject/issues/1902 |
1342 | | */ |
1343 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
1344 | 0 | PJSIP_EVENT_TRANSPORT_ERROR, NULL, |
1345 | 0 | NO_NOTIFY | NO_SCHEDULE_HANDLER); |
1346 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1347 | | |
1348 | | /* Now notify TU about state change, WITHOUT holding the |
1349 | | * group lock. It should be safe to do so; transaction will |
1350 | | * not get destroyed because group lock reference counter |
1351 | | * has been incremented by the timer heap. |
1352 | | */ |
1353 | 0 | if (tsx->tsx_user && tsx->tsx_user->on_tsx_state) { |
1354 | 0 | pjsip_event e; |
1355 | 0 | PJSIP_EVENT_INIT_TSX_STATE(e, tsx, |
1356 | 0 | PJSIP_EVENT_TRANSPORT_ERROR, NULL, |
1357 | 0 | prev_state); |
1358 | 0 | (*tsx->tsx_user->on_tsx_state)(tsx, &e); |
1359 | 0 | } |
1360 | | |
1361 | | /* Now let's schedule the tsx handler */ |
1362 | 0 | tsx_schedule_timer(tsx, &tsx->timeout_timer, &timeout, |
1363 | 0 | TIMEOUT_TIMER); |
1364 | 0 | } |
1365 | 0 | } else { |
1366 | 0 | pjsip_event event; |
1367 | |
|
1368 | 0 | entry->id = 0; |
1369 | |
|
1370 | 0 | PJ_LOG(5,(tsx->obj_name, "%s timer event", |
1371 | 0 | (entry==&tsx->retransmit_timer ? "Retransmit":"Timeout"))); |
1372 | 0 | pj_log_push_indent(); |
1373 | | |
1374 | |
|
1375 | 0 | PJSIP_EVENT_INIT_TIMER(event, entry); |
1376 | | |
1377 | | /* Dispatch event to transaction. */ |
1378 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
1379 | 0 | (*tsx->state_handler)(tsx, &event); |
1380 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1381 | |
|
1382 | 0 | pj_log_pop_indent(); |
1383 | 0 | } |
1384 | 0 | } |
1385 | | |
1386 | | |
1387 | | /* |
1388 | | * Set transaction state, and inform TU about the transaction state change. |
1389 | | */ |
1390 | | static void tsx_set_state( pjsip_transaction *tsx, |
1391 | | pjsip_tsx_state_e state, |
1392 | | pjsip_event_id_e event_src_type, |
1393 | | void *event_src, |
1394 | | int flag) |
1395 | 0 | { |
1396 | 0 | pjsip_tsx_state_e prev_state = tsx->state; |
1397 | | |
1398 | | /* New state must be greater than previous state */ |
1399 | 0 | pj_assert(state >= tsx->state); |
1400 | |
|
1401 | 0 | PJ_LOG(5, (tsx->obj_name, "State changed from %s to %s, event=%s", |
1402 | 0 | state_str[tsx->state], state_str[state], |
1403 | 0 | pjsip_event_str(event_src_type))); |
1404 | 0 | pj_log_push_indent(); |
1405 | | |
1406 | | /* Change state. */ |
1407 | 0 | tsx->state = state; |
1408 | | |
1409 | | /* Update the state handlers. */ |
1410 | 0 | if (tsx->role == PJSIP_ROLE_UAC) { |
1411 | 0 | tsx->state_handler = tsx_state_handler_uac[state]; |
1412 | 0 | } else { |
1413 | 0 | tsx->state_handler = tsx_state_handler_uas[state]; |
1414 | 0 | } |
1415 | | |
1416 | | /* Before informing TU about state changed, inform TU about |
1417 | | * rx event. |
1418 | | */ |
1419 | 0 | if (event_src_type==PJSIP_EVENT_RX_MSG && tsx->tsx_user && |
1420 | 0 | (flag & NO_NOTIFY)==0) |
1421 | 0 | { |
1422 | 0 | pjsip_rx_data *rdata = (pjsip_rx_data*) event_src; |
1423 | |
|
1424 | 0 | pj_assert(rdata != NULL); |
1425 | |
|
1426 | 0 | if (rdata->msg_info.msg->type == PJSIP_RESPONSE_MSG && |
1427 | 0 | tsx->tsx_user->on_rx_response) |
1428 | 0 | { |
1429 | 0 | (*tsx->tsx_user->on_rx_response)(rdata); |
1430 | 0 | } |
1431 | |
|
1432 | 0 | } |
1433 | | |
1434 | | /* Inform TU about state changed. */ |
1435 | 0 | if (tsx->tsx_user && tsx->tsx_user->on_tsx_state && |
1436 | 0 | (flag & NO_NOTIFY) == 0) |
1437 | 0 | { |
1438 | 0 | pjsip_event e; |
1439 | 0 | PJSIP_EVENT_INIT_TSX_STATE(e, tsx, event_src_type, event_src, |
1440 | 0 | prev_state); |
1441 | | |
1442 | | /* For timer event, release lock to avoid deadlock. |
1443 | | * This should be safe because: |
1444 | | * 1. The tsx state just switches to TERMINATED or DESTROYED. |
1445 | | * 2. There should be no other processing taking place. All other |
1446 | | * events, such as the ones handled by tsx_on_state_terminated() |
1447 | | * should be ignored. |
1448 | | * 3. tsx_shutdown() hasn't been called. |
1449 | | * Refer to ticket #2001 (https://github.com/pjsip/pjproject/issues/2001). |
1450 | | */ |
1451 | 0 | if ((flag & RELEASE_LOCK) != 0 || |
1452 | 0 | (event_src_type == PJSIP_EVENT_TIMER && |
1453 | 0 | (pj_timer_entry *)event_src == &tsx->timeout_timer)) |
1454 | 0 | { |
1455 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1456 | 0 | } |
1457 | |
|
1458 | 0 | (*tsx->tsx_user->on_tsx_state)(tsx, &e); |
1459 | |
|
1460 | 0 | if ((flag & RELEASE_LOCK) != 0 || |
1461 | 0 | (event_src_type == PJSIP_EVENT_TIMER && |
1462 | 0 | (pj_timer_entry *)event_src == &tsx->timeout_timer)) |
1463 | 0 | { |
1464 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
1465 | 0 | } |
1466 | 0 | } |
1467 | | |
1468 | | |
1469 | | /* When the transaction is terminated, release transport, and free the |
1470 | | * saved last transmitted message. |
1471 | | */ |
1472 | 0 | if (state == PJSIP_TSX_STATE_TERMINATED) { |
1473 | 0 | pj_time_val timeout = { 0, 0 }; |
1474 | | |
1475 | | /* If we're still waiting for a message to be sent.. */ |
1476 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { |
1477 | | /* Disassociate ourselves from the outstanding transmit data |
1478 | | * so that when the send callback is called we will be able |
1479 | | * to ignore that (otherwise we'll get assertion, see |
1480 | | * https://github.com/pjsip/pjproject/issues/1033) |
1481 | | */ |
1482 | 0 | if (tsx->pending_tx) { |
1483 | 0 | tsx->pending_tx->mod_data[mod_tsx_layer.mod.id] = NULL; |
1484 | 0 | tsx->pending_tx = NULL; |
1485 | | |
1486 | | /* Decrease pending send counter */ |
1487 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
1488 | 0 | } |
1489 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); |
1490 | 0 | } |
1491 | |
|
1492 | 0 | lock_timer(tsx); |
1493 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
1494 | 0 | if ((flag & NO_SCHEDULE_HANDLER) == 0) { |
1495 | 0 | tsx_schedule_timer(tsx, &tsx->timeout_timer, &timeout, |
1496 | 0 | TIMEOUT_TIMER); |
1497 | 0 | } |
1498 | 0 | unlock_timer(tsx); |
1499 | |
|
1500 | 0 | } else if (state == PJSIP_TSX_STATE_DESTROYED) { |
1501 | | |
1502 | | /* Unregister transaction. */ |
1503 | 0 | mod_tsx_layer_unregister_tsx(tsx); |
1504 | | |
1505 | | /* Destroy transaction. */ |
1506 | 0 | tsx_shutdown(tsx); |
1507 | 0 | } |
1508 | |
|
1509 | 0 | pj_log_pop_indent(); |
1510 | 0 | } |
1511 | | |
1512 | | /* |
1513 | | * Create, initialize, and register UAC transaction. |
1514 | | */ |
1515 | | PJ_DEF(pj_status_t) pjsip_tsx_create_uac( pjsip_module *tsx_user, |
1516 | | pjsip_tx_data *tdata, |
1517 | | pjsip_transaction **p_tsx) |
1518 | 0 | { |
1519 | 0 | return pjsip_tsx_create_uac2(tsx_user, tdata, NULL, p_tsx); |
1520 | 0 | } |
1521 | | |
1522 | | PJ_DEF(pj_status_t) pjsip_tsx_create_uac2(pjsip_module *tsx_user, |
1523 | | pjsip_tx_data *tdata, |
1524 | | pj_grp_lock_t *grp_lock, |
1525 | | pjsip_transaction **p_tsx) |
1526 | 0 | { |
1527 | 0 | pjsip_transaction *tsx; |
1528 | 0 | pjsip_msg *msg; |
1529 | 0 | pjsip_cseq_hdr *cseq; |
1530 | 0 | pjsip_via_hdr *via; |
1531 | 0 | pjsip_host_info dst_info; |
1532 | 0 | pj_status_t status; |
1533 | | |
1534 | | /* Validate arguments. */ |
1535 | 0 | PJ_ASSERT_RETURN(tdata && tdata->msg && p_tsx, PJ_EINVAL); |
1536 | 0 | PJ_ASSERT_RETURN(tdata->msg->type == PJSIP_REQUEST_MSG, |
1537 | 0 | PJSIP_ENOTREQUESTMSG); |
1538 | | |
1539 | | /* Method MUST NOT be ACK! */ |
1540 | 0 | PJ_ASSERT_RETURN(tdata->msg->line.req.method.id != PJSIP_ACK_METHOD, |
1541 | 0 | PJ_EINVALIDOP); |
1542 | | |
1543 | | /* Keep shortcut */ |
1544 | 0 | msg = tdata->msg; |
1545 | | |
1546 | | /* Make sure CSeq header is present. */ |
1547 | 0 | cseq = (pjsip_cseq_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_CSEQ, NULL); |
1548 | 0 | if (!cseq) { |
1549 | 0 | pj_assert(!"CSeq header not present in outgoing message!"); |
1550 | 0 | return PJSIP_EMISSINGHDR; |
1551 | 0 | } |
1552 | | |
1553 | | |
1554 | | /* Create transaction instance. */ |
1555 | 0 | status = tsx_create( tsx_user, grp_lock, &tsx); |
1556 | 0 | if (status != PJ_SUCCESS) |
1557 | 0 | return status; |
1558 | | |
1559 | | |
1560 | | /* Lock transaction. |
1561 | | * We don't need to lock the group lock if none was supplied, while the |
1562 | | * newly created group lock has not been exposed. |
1563 | | */ |
1564 | 0 | if (grp_lock) |
1565 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
1566 | | |
1567 | | /* Role is UAC. */ |
1568 | 0 | tsx->role = PJSIP_ROLE_UAC; |
1569 | | |
1570 | | /* Save method. */ |
1571 | 0 | pjsip_method_copy( tsx->pool, &tsx->method, &msg->line.req.method); |
1572 | | |
1573 | | /* Save CSeq. */ |
1574 | 0 | tsx->cseq = cseq->cseq; |
1575 | | |
1576 | | /* Generate Via header if it doesn't exist. */ |
1577 | 0 | via = (pjsip_via_hdr*) pjsip_msg_find_hdr(msg, PJSIP_H_VIA, NULL); |
1578 | 0 | if (via == NULL) { |
1579 | 0 | via = pjsip_via_hdr_create(tdata->pool); |
1580 | 0 | pjsip_msg_insert_first_hdr(msg, (pjsip_hdr*) via); |
1581 | 0 | } |
1582 | | |
1583 | | /* Generate branch parameter if it doesn't exist. */ |
1584 | 0 | if (via->branch_param.slen == 0) { |
1585 | 0 | pj_str_t tmp; |
1586 | 0 | via->branch_param.ptr = (char*) |
1587 | 0 | pj_pool_alloc(tsx->pool, PJSIP_MAX_BRANCH_LEN); |
1588 | 0 | via->branch_param.slen = PJSIP_MAX_BRANCH_LEN; |
1589 | 0 | pj_memcpy(via->branch_param.ptr, PJSIP_RFC3261_BRANCH_ID, |
1590 | 0 | PJSIP_RFC3261_BRANCH_LEN); |
1591 | 0 | tmp.ptr = via->branch_param.ptr + PJSIP_RFC3261_BRANCH_LEN + 2; |
1592 | 0 | *(tmp.ptr-2) = 80; *(tmp.ptr-1) = 106; |
1593 | 0 | pj_generate_unique_string( &tmp ); |
1594 | | |
1595 | | /* Save branch parameter. */ |
1596 | 0 | tsx->branch = via->branch_param; |
1597 | |
|
1598 | 0 | } else { |
1599 | | /* Copy branch parameter. */ |
1600 | 0 | pj_strdup(tsx->pool, &tsx->branch, &via->branch_param); |
1601 | 0 | } |
1602 | | |
1603 | | /* Generate transaction key. */ |
1604 | 0 | create_tsx_key_3261( tsx->pool, &tsx->transaction_key, |
1605 | 0 | PJSIP_ROLE_UAC, &tsx->method, |
1606 | 0 | &via->branch_param); |
1607 | | |
1608 | | /* Calculate hashed key value. */ |
1609 | 0 | #ifdef PRECALC_HASH |
1610 | 0 | tsx->hashed_key = pj_hash_calc_tolower(0, NULL, &tsx->transaction_key); |
1611 | 0 | #endif |
1612 | |
|
1613 | 0 | PJ_LOG(6, (tsx->obj_name, "tsx_key=%.*s", (int)tsx->transaction_key.slen, |
1614 | 0 | tsx->transaction_key.ptr)); |
1615 | | |
1616 | | /* Begin with State_Null. |
1617 | | * Manually set-up the state becase we don't want to call the callback. |
1618 | | */ |
1619 | 0 | tsx->state = PJSIP_TSX_STATE_NULL; |
1620 | 0 | tsx->state_handler = &tsx_on_state_null; |
1621 | | |
1622 | | /* Save the message. */ |
1623 | 0 | tsx->last_tx = tdata; |
1624 | 0 | pjsip_tx_data_add_ref(tsx->last_tx); |
1625 | | |
1626 | | /* Determine whether reliable transport should be used initially. |
1627 | | * This will be updated whenever transport has changed. |
1628 | | */ |
1629 | 0 | status = pjsip_get_request_dest(tdata, &dst_info); |
1630 | 0 | if (status != PJ_SUCCESS) { |
1631 | 0 | if (grp_lock) |
1632 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1633 | 0 | tsx_shutdown(tsx); |
1634 | 0 | return status; |
1635 | 0 | } |
1636 | 0 | tsx->is_reliable = (dst_info.flag & PJSIP_TRANSPORT_RELIABLE); |
1637 | | |
1638 | | /* Register transaction to hash table. */ |
1639 | 0 | status = mod_tsx_layer_register_tsx(tsx); |
1640 | 0 | if (status != PJ_SUCCESS) { |
1641 | | /* The assertion is removed by #1090: |
1642 | | pj_assert(!"Bug in branch_param generator (i.e. not unique)"); |
1643 | | */ |
1644 | 0 | if (grp_lock) |
1645 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1646 | 0 | tsx_shutdown(tsx); |
1647 | 0 | return status; |
1648 | 0 | } |
1649 | | |
1650 | | |
1651 | | /* Unlock transaction and return. */ |
1652 | 0 | if (grp_lock) |
1653 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1654 | |
|
1655 | 0 | pj_log_push_indent(); |
1656 | 0 | PJ_LOG(5,(tsx->obj_name, "Transaction created for %s", |
1657 | 0 | pjsip_tx_data_get_info(tdata))); |
1658 | 0 | pj_log_pop_indent(); |
1659 | |
|
1660 | 0 | *p_tsx = tsx; |
1661 | 0 | return PJ_SUCCESS; |
1662 | 0 | } |
1663 | | |
1664 | | |
1665 | | /* |
1666 | | * Create, initialize, and register UAS transaction. |
1667 | | */ |
1668 | | PJ_DEF(pj_status_t) pjsip_tsx_create_uas( pjsip_module *tsx_user, |
1669 | | pjsip_rx_data *rdata, |
1670 | | pjsip_transaction **p_tsx) |
1671 | 0 | { |
1672 | 0 | return pjsip_tsx_create_uas2(tsx_user, rdata, NULL, p_tsx); |
1673 | 0 | } |
1674 | | |
1675 | | PJ_DEF(pj_status_t) pjsip_tsx_create_uas2(pjsip_module *tsx_user, |
1676 | | pjsip_rx_data *rdata, |
1677 | | pj_grp_lock_t *grp_lock, |
1678 | | pjsip_transaction **p_tsx) |
1679 | 0 | { |
1680 | 0 | pjsip_transaction *tsx; |
1681 | 0 | pjsip_msg *msg; |
1682 | 0 | pj_str_t *branch; |
1683 | 0 | pjsip_cseq_hdr *cseq; |
1684 | 0 | pj_status_t status; |
1685 | | |
1686 | | /* Validate arguments. */ |
1687 | 0 | PJ_ASSERT_RETURN(rdata && rdata->msg_info.msg && p_tsx, PJ_EINVAL); |
1688 | | |
1689 | | /* Keep shortcut to message */ |
1690 | 0 | msg = rdata->msg_info.msg; |
1691 | | |
1692 | | /* Make sure this is a request message. */ |
1693 | 0 | PJ_ASSERT_RETURN(msg->type == PJSIP_REQUEST_MSG, PJSIP_ENOTREQUESTMSG); |
1694 | | |
1695 | | /* Make sure method is not ACK */ |
1696 | 0 | PJ_ASSERT_RETURN(msg->line.req.method.id != PJSIP_ACK_METHOD, |
1697 | 0 | PJ_EINVALIDOP); |
1698 | | |
1699 | | /* Make sure CSeq header is present. */ |
1700 | 0 | cseq = rdata->msg_info.cseq; |
1701 | 0 | if (!cseq) |
1702 | 0 | return PJSIP_EMISSINGHDR; |
1703 | | |
1704 | | /* Make sure Via header is present. */ |
1705 | 0 | if (rdata->msg_info.via == NULL) |
1706 | 0 | return PJSIP_EMISSINGHDR; |
1707 | | |
1708 | | /* Check that method in CSeq header match request method. |
1709 | | * Reference: PROTOS #1922 |
1710 | | */ |
1711 | 0 | if (pjsip_method_cmp(&msg->line.req.method, |
1712 | 0 | &rdata->msg_info.cseq->method) != 0) |
1713 | 0 | { |
1714 | 0 | PJ_LOG(4,(THIS_FILE, "Error: CSeq header contains different " |
1715 | 0 | "method than the request line")); |
1716 | 0 | return PJSIP_EINVALIDHDR; |
1717 | 0 | } |
1718 | | |
1719 | | /* |
1720 | | * Create transaction instance. |
1721 | | */ |
1722 | 0 | status = tsx_create( tsx_user, grp_lock, &tsx); |
1723 | 0 | if (status != PJ_SUCCESS) |
1724 | 0 | return status; |
1725 | | |
1726 | | |
1727 | | /* Lock transaction. */ |
1728 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
1729 | | |
1730 | | /* Role is UAS */ |
1731 | 0 | tsx->role = PJSIP_ROLE_UAS; |
1732 | | |
1733 | | /* Save method. */ |
1734 | 0 | pjsip_method_copy( tsx->pool, &tsx->method, &msg->line.req.method); |
1735 | | |
1736 | | /* Save CSeq */ |
1737 | 0 | tsx->cseq = cseq->cseq; |
1738 | | |
1739 | | /* Get transaction key either from branch for RFC3261 message, or |
1740 | | * create transaction key. |
1741 | | */ |
1742 | 0 | status = pjsip_tsx_create_key(tsx->pool, &tsx->transaction_key, |
1743 | 0 | PJSIP_ROLE_UAS, &tsx->method, rdata); |
1744 | 0 | if (status != PJ_SUCCESS) { |
1745 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1746 | 0 | tsx_shutdown(tsx); |
1747 | 0 | return status; |
1748 | 0 | } |
1749 | | |
1750 | | /* Create transaction key to detect merged requests, with the key |
1751 | | * consisting of From tag, CSeq, and Call-ID. |
1752 | | */ |
1753 | 0 | status = create_tsx_key_2543(tsx->pool, &tsx->transaction_key2, |
1754 | 0 | PJSIP_ROLE_UAS, &tsx->method, rdata, |
1755 | 0 | PJ_FALSE ); |
1756 | 0 | if (status != PJ_SUCCESS) { |
1757 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1758 | 0 | tsx_shutdown(tsx); |
1759 | 0 | return status; |
1760 | 0 | } |
1761 | | |
1762 | | /* Calculate hashed key value. */ |
1763 | 0 | #ifdef PRECALC_HASH |
1764 | 0 | tsx->hashed_key = pj_hash_calc_tolower(0, NULL, &tsx->transaction_key); |
1765 | 0 | tsx->hashed_key2 = pj_hash_calc_tolower(0, NULL, &tsx->transaction_key2); |
1766 | 0 | #endif |
1767 | | |
1768 | | /* Duplicate branch parameter for transaction. */ |
1769 | 0 | branch = &rdata->msg_info.via->branch_param; |
1770 | 0 | pj_strdup(tsx->pool, &tsx->branch, branch); |
1771 | |
|
1772 | 0 | PJ_LOG(6, (tsx->obj_name, "tsx_key=%.*s", (int)tsx->transaction_key.slen, |
1773 | 0 | tsx->transaction_key.ptr)); |
1774 | | |
1775 | | |
1776 | | /* Begin with state NULL. |
1777 | | * Manually set-up the state becase we don't want to call the callback. |
1778 | | */ |
1779 | 0 | tsx->state = PJSIP_TSX_STATE_NULL; |
1780 | 0 | tsx->state_handler = &tsx_on_state_null; |
1781 | | |
1782 | | /* Get response address. */ |
1783 | 0 | status = pjsip_get_response_addr( tsx->pool, rdata, &tsx->res_addr ); |
1784 | 0 | if (status != PJ_SUCCESS) { |
1785 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1786 | 0 | tsx_shutdown(tsx); |
1787 | 0 | return status; |
1788 | 0 | } |
1789 | | |
1790 | | /* If it's decided that we should use current transport, keep the |
1791 | | * transport. |
1792 | | */ |
1793 | 0 | if (tsx->res_addr.transport) { |
1794 | 0 | tsx_update_transport(tsx, tsx->res_addr.transport); |
1795 | 0 | pj_memcpy(&tsx->addr, &tsx->res_addr.addr, tsx->res_addr.addr_len); |
1796 | 0 | tsx->addr_len = tsx->res_addr.addr_len; |
1797 | 0 | tsx->is_reliable = PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport); |
1798 | 0 | } else { |
1799 | 0 | tsx->is_reliable = |
1800 | 0 | (tsx->res_addr.dst_host.flag & PJSIP_TRANSPORT_RELIABLE); |
1801 | 0 | } |
1802 | | |
1803 | | |
1804 | | /* Register the transaction. */ |
1805 | 0 | status = mod_tsx_layer_register_tsx(tsx); |
1806 | 0 | if (status != PJ_SUCCESS) { |
1807 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1808 | 0 | tsx_shutdown(tsx); |
1809 | 0 | return status; |
1810 | 0 | } |
1811 | | |
1812 | | /* Put this transaction in rdata's mod_data. */ |
1813 | 0 | rdata->endpt_info.mod_data[mod_tsx_layer.mod.id] = tsx; |
1814 | | |
1815 | | /* Unlock transaction and return. */ |
1816 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1817 | |
|
1818 | 0 | pj_log_push_indent(); |
1819 | 0 | PJ_LOG(5,(tsx->obj_name, "Transaction created for %s", |
1820 | 0 | pjsip_rx_data_get_info(rdata))); |
1821 | 0 | pj_log_pop_indent(); |
1822 | | |
1823 | |
|
1824 | 0 | *p_tsx = tsx; |
1825 | 0 | return PJ_SUCCESS; |
1826 | 0 | } |
1827 | | |
1828 | | |
1829 | | /* |
1830 | | * Bind transaction to a specific transport/listener. |
1831 | | */ |
1832 | | PJ_DEF(pj_status_t) pjsip_tsx_set_transport(pjsip_transaction *tsx, |
1833 | | const pjsip_tpselector *sel) |
1834 | 0 | { |
1835 | | /* Must be UAC transaction */ |
1836 | 0 | PJ_ASSERT_RETURN(tsx && sel, PJ_EINVAL); |
1837 | | |
1838 | | /* Start locking the transaction. */ |
1839 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
1840 | | |
1841 | | /* Decrement reference counter of previous transport selector */ |
1842 | 0 | pjsip_tpselector_dec_ref(&tsx->tp_sel); |
1843 | | |
1844 | | /* Copy transport selector structure .*/ |
1845 | 0 | pj_memcpy(&tsx->tp_sel, sel, sizeof(*sel)); |
1846 | | |
1847 | | /* Increment reference counter */ |
1848 | 0 | pjsip_tpselector_add_ref(&tsx->tp_sel); |
1849 | | |
1850 | | /* Unlock transaction. */ |
1851 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1852 | |
|
1853 | 0 | return PJ_SUCCESS; |
1854 | 0 | } |
1855 | | |
1856 | | |
1857 | | /* |
1858 | | * Set transaction status code and reason. |
1859 | | */ |
1860 | | static void tsx_set_status_code(pjsip_transaction *tsx, |
1861 | | int code, const pj_str_t *reason) |
1862 | 0 | { |
1863 | 0 | tsx->status_code = code; |
1864 | 0 | if (reason) |
1865 | 0 | pj_strdup(tsx->pool, &tsx->status_text, reason); |
1866 | 0 | else |
1867 | 0 | tsx->status_text = *pjsip_get_status_text(code); |
1868 | 0 | } |
1869 | | |
1870 | | |
1871 | | /* |
1872 | | * Forcely terminate transaction. |
1873 | | */ |
1874 | | PJ_DEF(pj_status_t) pjsip_tsx_terminate( pjsip_transaction *tsx, int code ) |
1875 | 0 | { |
1876 | 0 | PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL); |
1877 | | |
1878 | 0 | PJ_LOG(5,(tsx->obj_name, "Request to terminate transaction")); |
1879 | |
|
1880 | 0 | PJ_ASSERT_RETURN(code >= 200, PJ_EINVAL); |
1881 | | |
1882 | 0 | pj_log_push_indent(); |
1883 | |
|
1884 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
1885 | |
|
1886 | 0 | if (tsx->state < PJSIP_TSX_STATE_TERMINATED) { |
1887 | 0 | tsx_set_status_code(tsx, code, NULL); |
1888 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, PJSIP_EVENT_USER, |
1889 | 0 | NULL, 0); |
1890 | 0 | } |
1891 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1892 | |
|
1893 | 0 | pj_log_pop_indent(); |
1894 | |
|
1895 | 0 | return PJ_SUCCESS; |
1896 | 0 | } |
1897 | | |
1898 | | |
1899 | | /* |
1900 | | * Force terminate transaction asynchronously, using the transaction |
1901 | | * internal timer. |
1902 | | */ |
1903 | | PJ_DEF(pj_status_t) pjsip_tsx_terminate_async(pjsip_transaction *tsx, |
1904 | | int code ) |
1905 | 0 | { |
1906 | 0 | pj_time_val delay = {0, 100}; |
1907 | |
|
1908 | 0 | PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL); |
1909 | | |
1910 | 0 | PJ_LOG(5,(tsx->obj_name, "Request to terminate transaction async")); |
1911 | |
|
1912 | 0 | PJ_ASSERT_RETURN(code >= 200, PJ_EINVAL); |
1913 | | |
1914 | 0 | lock_timer(tsx); |
1915 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
1916 | 0 | tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, TERMINATE_TIMER); |
1917 | 0 | unlock_timer(tsx); |
1918 | |
|
1919 | 0 | return PJ_SUCCESS; |
1920 | 0 | } |
1921 | | |
1922 | | |
1923 | | /* |
1924 | | * Cease retransmission on the UAC transaction. The UAC transaction is |
1925 | | * still considered running, and it will complete when either final |
1926 | | * response is received or the transaction times out. |
1927 | | */ |
1928 | | PJ_DEF(pj_status_t) pjsip_tsx_stop_retransmit(pjsip_transaction *tsx) |
1929 | 0 | { |
1930 | 0 | PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL); |
1931 | 0 | PJ_ASSERT_RETURN(tsx->role == PJSIP_ROLE_UAC && |
1932 | 0 | tsx->method.id == PJSIP_INVITE_METHOD, |
1933 | 0 | PJ_EINVALIDOP); |
1934 | | |
1935 | 0 | PJ_LOG(5,(tsx->obj_name, "Request to stop retransmission")); |
1936 | |
|
1937 | 0 | pj_log_push_indent(); |
1938 | |
|
1939 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
1940 | | /* Cancel retransmission timer. */ |
1941 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
1942 | 0 | pj_grp_lock_release(tsx->grp_lock); |
1943 | |
|
1944 | 0 | pj_log_pop_indent(); |
1945 | |
|
1946 | 0 | return PJ_SUCCESS; |
1947 | 0 | } |
1948 | | |
1949 | | |
1950 | | /* |
1951 | | * Start a timer to terminate transaction after the specified time |
1952 | | * has elapsed. |
1953 | | */ |
1954 | | PJ_DEF(pj_status_t) pjsip_tsx_set_timeout( pjsip_transaction *tsx, |
1955 | | unsigned millisec) |
1956 | 0 | { |
1957 | 0 | pj_time_val timeout; |
1958 | |
|
1959 | 0 | PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL); |
1960 | 0 | PJ_ASSERT_RETURN(tsx->role == PJSIP_ROLE_UAC && |
1961 | 0 | tsx->method.id == PJSIP_INVITE_METHOD, |
1962 | 0 | PJ_EINVALIDOP); |
1963 | | |
1964 | | /* Note: must not call pj_grp_lock_acquire(tsx->grp_lock) as |
1965 | | * that would introduce deadlock. See #1121. |
1966 | | */ |
1967 | 0 | lock_timer(tsx); |
1968 | | |
1969 | | /* Transaction should normally not have final response, but as |
1970 | | * #1121 says there is a (tolerable) window of race condition |
1971 | | * where this might happen. |
1972 | | */ |
1973 | 0 | if (tsx->status_code >= 200 && tsx->timeout_timer.id != 0) { |
1974 | | /* Timeout is already set */ |
1975 | 0 | unlock_timer(tsx); |
1976 | 0 | return PJ_EEXISTS; |
1977 | 0 | } |
1978 | | |
1979 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
1980 | |
|
1981 | 0 | timeout.sec = 0; |
1982 | 0 | timeout.msec = millisec; |
1983 | 0 | pj_time_val_normalize(&timeout); |
1984 | |
|
1985 | 0 | tsx_schedule_timer(tsx, &tsx->timeout_timer, &timeout, TIMEOUT_TIMER); |
1986 | |
|
1987 | 0 | unlock_timer(tsx); |
1988 | |
|
1989 | 0 | return PJ_SUCCESS; |
1990 | 0 | } |
1991 | | |
1992 | | |
1993 | | /* |
1994 | | * This function is called by TU to send a message. |
1995 | | */ |
1996 | | PJ_DEF(pj_status_t) pjsip_tsx_send_msg( pjsip_transaction *tsx, |
1997 | | pjsip_tx_data *tdata ) |
1998 | 0 | { |
1999 | 0 | pjsip_event event; |
2000 | 0 | pj_status_t status; |
2001 | |
|
2002 | 0 | if (tdata == NULL) |
2003 | 0 | tdata = tsx->last_tx; |
2004 | |
|
2005 | 0 | PJ_ASSERT_RETURN(tdata != NULL, PJ_EINVALIDOP); |
2006 | | |
2007 | 0 | PJ_LOG(5,(tsx->obj_name, "Sending %s in state %s", |
2008 | 0 | pjsip_tx_data_get_info(tdata), |
2009 | 0 | state_str[tsx->state])); |
2010 | 0 | pj_log_push_indent(); |
2011 | |
|
2012 | 0 | PJSIP_EVENT_INIT_TX_MSG(event, tdata); |
2013 | | |
2014 | | /* Dispatch to transaction. */ |
2015 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
2016 | | |
2017 | | /* Set transport selector to tdata */ |
2018 | 0 | pjsip_tx_data_set_transport(tdata, &tsx->tp_sel); |
2019 | | |
2020 | | /* Dispatch to state handler */ |
2021 | 0 | status = (*tsx->state_handler)(tsx, &event); |
2022 | |
|
2023 | 0 | pj_grp_lock_release(tsx->grp_lock); |
2024 | | |
2025 | | /* Only decrement reference counter when it returns success. |
2026 | | * (This is the specification from the .PDF design document). |
2027 | | */ |
2028 | 0 | if (status == PJ_SUCCESS) { |
2029 | 0 | pjsip_tx_data_dec_ref(tdata); |
2030 | 0 | } |
2031 | |
|
2032 | 0 | pj_log_pop_indent(); |
2033 | |
|
2034 | 0 | return status; |
2035 | 0 | } |
2036 | | |
2037 | | |
2038 | | /* |
2039 | | * This function is called by endpoint when incoming message for the |
2040 | | * transaction is received. |
2041 | | */ |
2042 | | PJ_DEF(void) pjsip_tsx_recv_msg( pjsip_transaction *tsx, |
2043 | | pjsip_rx_data *rdata) |
2044 | 0 | { |
2045 | 0 | pjsip_event event; |
2046 | |
|
2047 | 0 | PJ_LOG(5,(tsx->obj_name, "Incoming %s in state %s", |
2048 | 0 | pjsip_rx_data_get_info(rdata), state_str[tsx->state])); |
2049 | 0 | pj_log_push_indent(); |
2050 | | |
2051 | | /* Put the transaction in the rdata's mod_data. */ |
2052 | 0 | rdata->endpt_info.mod_data[mod_tsx_layer.mod.id] = tsx; |
2053 | | |
2054 | | /* Init event. */ |
2055 | 0 | PJSIP_EVENT_INIT_RX_MSG(event, rdata); |
2056 | | |
2057 | | /* Dispatch to transaction. */ |
2058 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
2059 | 0 | (*tsx->state_handler)(tsx, &event); |
2060 | 0 | pj_grp_lock_release(tsx->grp_lock); |
2061 | |
|
2062 | 0 | pj_log_pop_indent(); |
2063 | 0 | } |
2064 | | |
2065 | | |
2066 | | /* Callback called by send message framework */ |
2067 | | static void send_msg_callback( pjsip_send_state *send_state, |
2068 | | pj_ssize_t sent, pj_bool_t *cont ) |
2069 | 0 | { |
2070 | 0 | pjsip_transaction *tsx = (pjsip_transaction*) send_state->token; |
2071 | 0 | pjsip_tx_data *tdata = send_state->tdata; |
2072 | | |
2073 | | /* Check if transaction has cancelled itself from this transmit |
2074 | | * notification (https://github.com/pjsip/pjproject/issues/1033). |
2075 | | * Also check if the transaction layer itself may have been shutdown |
2076 | | * (https://github.com/pjsip/pjproject/issues/1535) |
2077 | | */ |
2078 | 0 | if (mod_tsx_layer.mod.id < 0 || |
2079 | 0 | tdata->mod_data[mod_tsx_layer.mod.id] == NULL) |
2080 | 0 | { |
2081 | 0 | *cont = PJ_FALSE; |
2082 | | |
2083 | | /* Decrease pending send counter, but only if the transaction layer |
2084 | | * hasn't been shutdown. |
2085 | | */ |
2086 | | // If tsx has cancelled itself from this transmit notification |
2087 | | // it should have also decreased pending send counter. |
2088 | | //if (mod_tsx_layer.mod.id >= 0) |
2089 | | // pj_grp_lock_dec_ref(tsx->grp_lock); |
2090 | |
|
2091 | 0 | return; |
2092 | 0 | } |
2093 | | |
2094 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
2095 | | |
2096 | | /* Decrease pending send counter */ |
2097 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
2098 | | |
2099 | | /* Reset */ |
2100 | 0 | tdata->mod_data[mod_tsx_layer.mod.id] = NULL; |
2101 | 0 | tsx->pending_tx = NULL; |
2102 | |
|
2103 | 0 | if (sent > 0) { |
2104 | | /* Successfully sent! */ |
2105 | 0 | pj_assert(send_state->cur_transport != NULL); |
2106 | |
|
2107 | 0 | if (tsx->transport != send_state->cur_transport) { |
2108 | | /* Update transport. */ |
2109 | 0 | tsx_update_transport(tsx, send_state->cur_transport); |
2110 | | |
2111 | | /* Update remote address. */ |
2112 | 0 | pj_assert(tdata->dest_info.cur_addr < |
2113 | 0 | PJ_ARRAY_SIZE(tdata->dest_info.addr.entry)); |
2114 | 0 | tsx->addr_len = tdata->dest_info.addr.entry[tdata->dest_info.cur_addr].addr_len; |
2115 | 0 | pj_memcpy(&tsx->addr, |
2116 | 0 | &tdata->dest_info.addr.entry[tdata->dest_info.cur_addr].addr, |
2117 | 0 | tsx->addr_len); |
2118 | | |
2119 | | /* Update is_reliable flag. */ |
2120 | 0 | tsx->is_reliable = PJSIP_TRANSPORT_IS_RELIABLE(tsx->transport); |
2121 | 0 | } |
2122 | | |
2123 | | /* Clear pending transport flag. */ |
2124 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); |
2125 | | |
2126 | | /* Mark that we have resolved the addresses. */ |
2127 | 0 | tsx->transport_flag |= TSX_HAS_RESOLVED_SERVER; |
2128 | | |
2129 | | /* Pending destroy? */ |
2130 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_DESTROY) { |
2131 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED, |
2132 | 0 | PJSIP_EVENT_UNKNOWN, NULL, 0 ); |
2133 | 0 | pj_grp_lock_release(tsx->grp_lock); |
2134 | 0 | return; |
2135 | 0 | } |
2136 | | |
2137 | | /* Need to transmit a message? */ |
2138 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_SEND) { |
2139 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_SEND); |
2140 | 0 | tsx_send_msg(tsx, tsx->last_tx); |
2141 | 0 | } |
2142 | | |
2143 | | /* Need to reschedule retransmission? |
2144 | | * Note that when sending a pending message above, tsx_send_msg() |
2145 | | * may set the flag TSX_HAS_PENDING_TRANSPORT. |
2146 | | * Please refer to ticket #1875. |
2147 | | */ |
2148 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_RESCHED && |
2149 | 0 | !(tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT)) |
2150 | 0 | { |
2151 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); |
2152 | | |
2153 | | /* Only update when transport turns out to be unreliable. */ |
2154 | 0 | if (!tsx->is_reliable) { |
2155 | 0 | tsx_resched_retransmission(tsx); |
2156 | 0 | } |
2157 | 0 | } |
2158 | |
|
2159 | 0 | } else { |
2160 | | /* Failed to send! */ |
2161 | 0 | pj_assert(sent != 0); |
2162 | | |
2163 | | /* If transaction is using the same transport as the failed one, |
2164 | | * release the transport. |
2165 | | */ |
2166 | 0 | if (send_state->cur_transport==tsx->transport) |
2167 | 0 | tsx_update_transport(tsx, NULL); |
2168 | | |
2169 | | /* Also stop processing if transaction has been flagged with |
2170 | | * pending destroy (https://github.com/pjsip/pjproject/issues/906) |
2171 | | * or if transaction is cancelled by app. |
2172 | | */ |
2173 | 0 | if ((!*cont) || (tsx->transport_flag & TSX_HAS_PENDING_DESTROY) || |
2174 | 0 | -sent == PJ_ECANCELLED) |
2175 | 0 | { |
2176 | 0 | char errmsg[PJ_ERR_MSG_SIZE]; |
2177 | 0 | pjsip_status_code sc; |
2178 | 0 | pj_str_t err; |
2179 | |
|
2180 | 0 | tsx->transport_err = (pj_status_t)-sent; |
2181 | |
|
2182 | 0 | err =pj_strerror((pj_status_t)-sent, errmsg, sizeof(errmsg)); |
2183 | |
|
2184 | 0 | PJ_LOG(3,(tsx->obj_name, |
2185 | 0 | "Failed to send %s! err=%ld (%s)", |
2186 | 0 | pjsip_tx_data_get_info(send_state->tdata), -sent, |
2187 | 0 | errmsg)); |
2188 | | |
2189 | | /* Clear pending transport flag. */ |
2190 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); |
2191 | | |
2192 | | /* Mark that we have resolved the addresses. */ |
2193 | 0 | tsx->transport_flag |= TSX_HAS_RESOLVED_SERVER; |
2194 | | |
2195 | | /* Server resolution error is now mapped to 502 instead of 503, |
2196 | | * since with 503 normally client should try again. |
2197 | | * See https://github.com/pjsip/pjproject/issues/870 |
2198 | | */ |
2199 | 0 | if (-sent==PJ_ERESOLVE || -sent==PJLIB_UTIL_EDNS_NXDOMAIN || |
2200 | 0 | -sent==PJ_ECANCELLED) |
2201 | 0 | { |
2202 | 0 | sc = PJSIP_SC_BAD_GATEWAY; |
2203 | 0 | } else { |
2204 | 0 | sc = PJSIP_SC_TSX_TRANSPORT_ERROR; |
2205 | 0 | } |
2206 | | |
2207 | | /* For UAC tsx, we directly terminate the transaction. |
2208 | | * For UAS tsx, we terminate the transaction for 502 error, |
2209 | | * and will retry for 503. |
2210 | | * See #3805 and #3806. |
2211 | | */ |
2212 | 0 | if ((tsx->role == PJSIP_ROLE_UAC || sc == PJSIP_SC_BAD_GATEWAY) && |
2213 | 0 | tsx->state != PJSIP_TSX_STATE_TERMINATED && |
2214 | 0 | tsx->state != PJSIP_TSX_STATE_DESTROYED) |
2215 | 0 | { |
2216 | 0 | tsx_set_status_code(tsx, sc, &err); |
2217 | | /* Set tsx state to TERMINATED, but release the lock |
2218 | | * when invoking the callback, to avoid deadlock. |
2219 | | */ |
2220 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
2221 | 0 | PJSIP_EVENT_TRANSPORT_ERROR, |
2222 | 0 | send_state->tdata, RELEASE_LOCK); |
2223 | 0 | } |
2224 | | /* Don't forget to destroy if we have pending destroy flag |
2225 | | * (https://github.com/pjsip/pjproject/issues/906) |
2226 | | */ |
2227 | 0 | else if (tsx->transport_flag & TSX_HAS_PENDING_DESTROY) |
2228 | 0 | { |
2229 | 0 | tsx_set_status_code(tsx, sc, &err); |
2230 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED, |
2231 | 0 | PJSIP_EVENT_TRANSPORT_ERROR, |
2232 | 0 | send_state->tdata, 0); |
2233 | 0 | } else if (tsx->role == PJSIP_ROLE_UAS && |
2234 | 0 | tsx->transport_flag & TSX_HAS_PENDING_RESCHED && |
2235 | 0 | tsx->state != PJSIP_TSX_STATE_TERMINATED && |
2236 | 0 | tsx->state != PJSIP_TSX_STATE_DESTROYED) |
2237 | 0 | { |
2238 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); |
2239 | 0 | tsx_resched_retransmission(tsx); |
2240 | 0 | } |
2241 | |
|
2242 | 0 | } else { |
2243 | 0 | PJ_PERROR(3,(tsx->obj_name, (pj_status_t)-sent, |
2244 | 0 | "Temporary failure in sending %s, " |
2245 | 0 | "will try next server", |
2246 | 0 | pjsip_tx_data_get_info(send_state->tdata))); |
2247 | | |
2248 | | /* Reset retransmission count */ |
2249 | 0 | tsx->retransmit_count = 0; |
2250 | | |
2251 | | /* And reset timeout timer */ |
2252 | 0 | if (tsx->timeout_timer.id) { |
2253 | 0 | lock_timer(tsx); |
2254 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
2255 | 0 | tsx_schedule_timer( tsx, &tsx->timeout_timer, |
2256 | 0 | &timeout_timer_val, TIMEOUT_TIMER); |
2257 | 0 | unlock_timer(tsx); |
2258 | 0 | } |
2259 | | |
2260 | | /* Put again pending tdata */ |
2261 | 0 | tdata->mod_data[mod_tsx_layer.mod.id] = tsx; |
2262 | 0 | tsx->pending_tx = tdata; |
2263 | | |
2264 | | /* Increment group lock again for the next sending retry, |
2265 | | * to prevent us from being destroyed prematurely (ticket #1859). |
2266 | | */ |
2267 | 0 | pj_grp_lock_add_ref(tsx->grp_lock); |
2268 | 0 | } |
2269 | 0 | } |
2270 | | |
2271 | 0 | pj_grp_lock_release(tsx->grp_lock); |
2272 | 0 | } |
2273 | | |
2274 | | |
2275 | | /* Transport callback parameter. */ |
2276 | | struct tp_cb_param { |
2277 | | pjsip_transaction* tsx; |
2278 | | pjsip_tx_data* tdata; |
2279 | | pj_ssize_t sent; |
2280 | | }; |
2281 | | |
2282 | | |
2283 | | /* Transport callback actual implementation. */ |
2284 | | static void transport_callback_impl(pjsip_transaction *tsx, |
2285 | | pjsip_tx_data* tdata, |
2286 | | pj_ssize_t sent) |
2287 | 0 | { |
2288 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
2289 | |
|
2290 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); |
2291 | |
|
2292 | 0 | if (sent > 0 || tsx->role == PJSIP_ROLE_UAS) { |
2293 | 0 | if (sent < 0) { |
2294 | | /* For UAS transactions, we just print error log |
2295 | | * and continue as per normal. |
2296 | | */ |
2297 | 0 | PJ_PERROR(2,(tsx->obj_name, (pj_status_t)-sent, |
2298 | 0 | "Transport failed to send %s!", |
2299 | 0 | pjsip_tx_data_get_info(tdata))); |
2300 | 0 | } |
2301 | | |
2302 | | /* Pending destroy? */ |
2303 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_DESTROY) { |
2304 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED, |
2305 | 0 | PJSIP_EVENT_UNKNOWN, NULL, 0 ); |
2306 | 0 | pj_grp_lock_release(tsx->grp_lock); |
2307 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
2308 | 0 | return; |
2309 | 0 | } |
2310 | | |
2311 | | /* Need to transmit a message? */ |
2312 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_SEND) { |
2313 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_SEND); |
2314 | 0 | tsx_send_msg(tsx, tsx->last_tx); |
2315 | 0 | } |
2316 | | |
2317 | | /* Need to reschedule retransmission? |
2318 | | * Note that when sending a pending message above, tsx_send_msg() |
2319 | | * may set the flag TSX_HAS_PENDING_TRANSPORT. |
2320 | | * Please refer to ticket #1875. |
2321 | | */ |
2322 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_RESCHED && |
2323 | 0 | !(tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT)) |
2324 | 0 | { |
2325 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); |
2326 | | |
2327 | | /* Only update when transport turns out to be unreliable. */ |
2328 | 0 | if (!tsx->is_reliable) { |
2329 | 0 | tsx_resched_retransmission(tsx); |
2330 | 0 | } |
2331 | 0 | } |
2332 | 0 | } |
2333 | 0 | pj_grp_lock_release(tsx->grp_lock); |
2334 | |
|
2335 | 0 | if (sent < 0 && tsx->role == PJSIP_ROLE_UAC) { |
2336 | 0 | pj_time_val delay = {0, 0}; |
2337 | |
|
2338 | 0 | PJ_PERROR(2,(tsx->obj_name, (pj_status_t)-sent, |
2339 | 0 | "Transport failed to send %s!", |
2340 | 0 | pjsip_tx_data_get_info(tdata))); |
2341 | | |
2342 | | /* Post the event for later processing, to avoid deadlock. |
2343 | | * See https://github.com/pjsip/pjproject/issues/1646 |
2344 | | */ |
2345 | 0 | lock_timer(tsx); |
2346 | 0 | tsx->transport_err = (pj_status_t)-sent; |
2347 | | /* Don't cancel timeout timer if tsx state is already |
2348 | | * PJSIP_TSX_STATE_COMPLETED (see #2076). |
2349 | | */ |
2350 | 0 | if (tsx->state < PJSIP_TSX_STATE_COMPLETED) { |
2351 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
2352 | 0 | tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, |
2353 | 0 | TRANSPORT_ERR_TIMER); |
2354 | 0 | } |
2355 | 0 | unlock_timer(tsx); |
2356 | 0 | } |
2357 | | |
2358 | | /* Decrease pending send counter */ |
2359 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
2360 | 0 | } |
2361 | | |
2362 | | |
2363 | | /* Timer callback for transport callback. |
2364 | | * This is currently only used to avoid deadlock due to inversed locking order |
2365 | | * between transport and transaction. |
2366 | | */ |
2367 | | static void tsx_misc_timer_callback(pj_timer_heap_t *theap, |
2368 | | pj_timer_entry *entry) |
2369 | 0 | { |
2370 | 0 | PJ_UNUSED_ARG(theap); |
2371 | |
|
2372 | 0 | if (entry->id == TRANSPORT_CB_TIMER) { |
2373 | 0 | struct tp_cb_param* param = (struct tp_cb_param*)entry->user_data; |
2374 | | |
2375 | | /* Check if the transaction layer has been shutdown. */ |
2376 | 0 | if (mod_tsx_layer.mod.id >= 0) { |
2377 | | /* Call transport callback implementation */ |
2378 | 0 | transport_callback_impl(param->tsx, param->tdata, param->sent); |
2379 | 0 | } |
2380 | | |
2381 | | /* Release tdata */ |
2382 | 0 | pjsip_tx_data_dec_ref(param->tdata); |
2383 | 0 | } |
2384 | 0 | } |
2385 | | |
2386 | | |
2387 | | /* Transport callback. */ |
2388 | | static void transport_callback(void *token, pjsip_tx_data *tdata, |
2389 | | pj_ssize_t sent) |
2390 | 0 | { |
2391 | 0 | pjsip_transaction *tsx = (pjsip_transaction*) token; |
2392 | 0 | pj_status_t status; |
2393 | | |
2394 | | /* Check if the transaction layer has been shutdown. */ |
2395 | 0 | if (mod_tsx_layer.mod.id < 0) |
2396 | 0 | return; |
2397 | | |
2398 | | /* In other circumstances, locking tsx->grp_lock AFTER transport mutex |
2399 | | * will introduce deadlock if another thread is currently sending a |
2400 | | * SIP message to the transport. But this should be safe as there should |
2401 | | * be no way this callback could be called while another thread is |
2402 | | * sending a message. |
2403 | | */ |
2404 | | // Deadlock does happen, see #4453. |
2405 | | // So now, to avoid deadlock, we'll try to acquire the group lock first, |
2406 | | // and if it fails, we'll schedule the processing via timer. |
2407 | 0 | status = pj_grp_lock_tryacquire(tsx->grp_lock); |
2408 | 0 | if (status != PJ_SUCCESS) { |
2409 | 0 | pj_time_val delay = { 0, 0 }; |
2410 | 0 | struct tp_cb_param *param = NULL; |
2411 | |
|
2412 | 0 | lock_timer(tsx); |
2413 | 0 | tsx_cancel_timer(tsx, &tsx->misc_timer); |
2414 | | |
2415 | | /* Increment tdata ref count to avoid premature destruction. |
2416 | | * Note that tsx ref count is already handled by tsx_schedule_timer(). |
2417 | | */ |
2418 | 0 | pjsip_tx_data_add_ref(tdata); |
2419 | |
|
2420 | 0 | param = PJ_POOL_ZALLOC_T(tsx->pool, struct tp_cb_param); |
2421 | 0 | param->sent = sent; |
2422 | 0 | param->tdata = tdata; |
2423 | 0 | param->tsx = tsx; |
2424 | 0 | pj_timer_entry_init(&tsx->misc_timer, TIMER_INACTIVE, param, |
2425 | 0 | &tsx_misc_timer_callback); |
2426 | 0 | tsx_schedule_timer(tsx, &tsx->misc_timer, &delay, TRANSPORT_CB_TIMER); |
2427 | 0 | unlock_timer(tsx); |
2428 | 0 | return; |
2429 | 0 | } |
2430 | | |
2431 | 0 | transport_callback_impl(tsx, tdata, sent); |
2432 | 0 | pj_grp_lock_release(tsx->grp_lock); |
2433 | 0 | } |
2434 | | |
2435 | | |
2436 | | /* |
2437 | | * Callback when transport state changes. |
2438 | | */ |
2439 | | static void tsx_tp_state_callback( pjsip_transport *tp, |
2440 | | pjsip_transport_state state, |
2441 | | const pjsip_transport_state_info *info) |
2442 | 0 | { |
2443 | 0 | PJ_UNUSED_ARG(tp); |
2444 | |
|
2445 | 0 | if (state == PJSIP_TP_STATE_DISCONNECTED) { |
2446 | 0 | pjsip_transaction *tsx; |
2447 | 0 | pj_time_val delay = {0, 0}; |
2448 | |
|
2449 | 0 | pj_assert(tp && info && info->user_data); |
2450 | |
|
2451 | 0 | tsx = (pjsip_transaction*)info->user_data; |
2452 | |
|
2453 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); |
2454 | | |
2455 | | /* Post the event for later processing, to avoid deadlock. |
2456 | | * See https://github.com/pjsip/pjproject/issues/1646 |
2457 | | */ |
2458 | 0 | lock_timer(tsx); |
2459 | 0 | tsx->transport_err = info->status; |
2460 | | /* Don't cancel timeout timer if tsx state is already |
2461 | | * PJSIP_TSX_STATE_COMPLETED (see #2076). |
2462 | | */ |
2463 | 0 | if (tsx->state < PJSIP_TSX_STATE_COMPLETED) { |
2464 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
2465 | 0 | tsx_schedule_timer(tsx, &tsx->timeout_timer, &delay, |
2466 | 0 | TRANSPORT_DISC_TIMER); |
2467 | 0 | } |
2468 | 0 | unlock_timer(tsx); |
2469 | 0 | } |
2470 | 0 | } |
2471 | | |
2472 | | |
2473 | | /* |
2474 | | * Send message to the transport. |
2475 | | */ |
2476 | | static pj_status_t tsx_send_msg( pjsip_transaction *tsx, |
2477 | | pjsip_tx_data *tdata) |
2478 | 0 | { |
2479 | 0 | pj_status_t status = PJ_SUCCESS; |
2480 | |
|
2481 | 0 | PJ_ASSERT_RETURN(tsx && tdata, PJ_EINVAL); |
2482 | | |
2483 | | /* Send later if transport is still pending. */ |
2484 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { |
2485 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_SEND; |
2486 | 0 | return PJ_SUCCESS; |
2487 | 0 | } |
2488 | | |
2489 | | /* Skip send if previous tdata transmission is pending (see #1665). */ |
2490 | 0 | if (tdata->is_pending) { |
2491 | 0 | PJ_LOG(2,(THIS_FILE, "Unable to send %s: message is pending", |
2492 | 0 | pjsip_tx_data_get_info(tdata))); |
2493 | 0 | return PJ_SUCCESS; |
2494 | 0 | } |
2495 | | |
2496 | | /* If we have the transport, send the message using that transport. |
2497 | | * Otherwise perform full transport resolution. |
2498 | | */ |
2499 | 0 | if (tsx->transport) { |
2500 | | /* Increment group lock while waiting for send operation to complete, |
2501 | | * to prevent us from being destroyed prematurely. See |
2502 | | * https://github.com/pjsip/pjproject/issues/1646 |
2503 | | */ |
2504 | 0 | pj_grp_lock_add_ref(tsx->grp_lock); |
2505 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_TRANSPORT; |
2506 | |
|
2507 | 0 | status = pjsip_transport_send( tsx->transport, tdata, &tsx->addr, |
2508 | 0 | tsx->addr_len, tsx, |
2509 | 0 | &transport_callback); |
2510 | 0 | if (status == PJ_EPENDING) |
2511 | 0 | status = PJ_SUCCESS; |
2512 | 0 | else { |
2513 | | /* Operation completes immediately */ |
2514 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); |
2515 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
2516 | 0 | } |
2517 | |
|
2518 | 0 | if (status != PJ_SUCCESS) { |
2519 | 0 | PJ_PERROR(2,(tsx->obj_name, status, |
2520 | 0 | "Error sending %s", |
2521 | 0 | pjsip_tx_data_get_info(tdata))); |
2522 | | |
2523 | | /* On error, release transport to force using full transport |
2524 | | * resolution procedure. |
2525 | | */ |
2526 | 0 | tsx_update_transport(tsx, NULL); |
2527 | |
|
2528 | 0 | tsx->addr_len = 0; |
2529 | 0 | tsx->res_addr.transport = NULL; |
2530 | 0 | tsx->res_addr.addr_len = 0; |
2531 | 0 | } else { |
2532 | 0 | return PJ_SUCCESS; |
2533 | 0 | } |
2534 | 0 | } |
2535 | | |
2536 | | /* We are here because we don't have transport, or we failed to send |
2537 | | * the message using existing transport. If we haven't resolved the |
2538 | | * server before, then begin the long process of resolving the server |
2539 | | * and send the message with possibly new server. |
2540 | | */ |
2541 | 0 | pj_assert(status != PJ_SUCCESS || tsx->transport == NULL); |
2542 | | |
2543 | | /* If we have resolved the server, we treat the error as permanent error. |
2544 | | * Terminate transaction with transport error failure. |
2545 | | * Only applicable for UAC transactions. |
2546 | | */ |
2547 | 0 | if (tsx->role == PJSIP_ROLE_UAC && |
2548 | 0 | (tsx->transport_flag & TSX_HAS_RESOLVED_SERVER)) |
2549 | 0 | { |
2550 | | |
2551 | 0 | char errmsg[PJ_ERR_MSG_SIZE]; |
2552 | 0 | pj_str_t err; |
2553 | |
|
2554 | 0 | if (status == PJ_SUCCESS) { |
2555 | 0 | pj_assert(!"Unexpected status!"); |
2556 | 0 | status = PJ_EUNKNOWN; |
2557 | 0 | } |
2558 | | |
2559 | | /* We have resolved the server!. |
2560 | | * Treat this as permanent transport error. |
2561 | | */ |
2562 | 0 | err = pj_strerror(status, errmsg, sizeof(errmsg)); |
2563 | |
|
2564 | 0 | PJ_LOG(2,(tsx->obj_name, |
2565 | 0 | "Transport error, terminating transaction. " |
2566 | 0 | "Err=%d (%s)", |
2567 | 0 | status, errmsg)); |
2568 | |
|
2569 | 0 | tsx_set_status_code(tsx, PJSIP_SC_TSX_TRANSPORT_ERROR, &err); |
2570 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
2571 | 0 | PJSIP_EVENT_TRANSPORT_ERROR, NULL, 0 ); |
2572 | |
|
2573 | 0 | return status; |
2574 | 0 | } |
2575 | | |
2576 | | /* Must add reference counter because the send request functions |
2577 | | * decrement the reference counter. |
2578 | | */ |
2579 | 0 | pjsip_tx_data_add_ref(tdata); |
2580 | | |
2581 | | /* Also attach ourselves to the transmit data so that we'll be able |
2582 | | * to unregister ourselves from the send notification of this |
2583 | | * transmit data. |
2584 | | */ |
2585 | 0 | tdata->mod_data[mod_tsx_layer.mod.id] = tsx; |
2586 | 0 | tsx->pending_tx = tdata; |
2587 | | |
2588 | | /* Increment group lock while waiting for send operation to complete, |
2589 | | * to prevent us from being destroyed prematurely (ticket #1859). |
2590 | | */ |
2591 | 0 | pj_grp_lock_add_ref(tsx->grp_lock); |
2592 | | |
2593 | | /* Begin resolving destination etc to send the message. */ |
2594 | 0 | if (tdata->msg->type == PJSIP_REQUEST_MSG) { |
2595 | |
|
2596 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_TRANSPORT; |
2597 | 0 | status = pjsip_endpt_send_request_stateless(tsx->endpt, tdata, tsx, |
2598 | 0 | &send_msg_callback); |
2599 | 0 | if (status == PJ_EPENDING) |
2600 | 0 | status = PJ_SUCCESS; |
2601 | 0 | if (status != PJ_SUCCESS) { |
2602 | 0 | char errmsg[PJ_ERR_MSG_SIZE]; |
2603 | 0 | pj_str_t err; |
2604 | |
|
2605 | 0 | err = pj_strerror(status, errmsg, sizeof(errmsg)); |
2606 | 0 | tsx_set_status_code(tsx, PJSIP_SC_TSX_TRANSPORT_ERROR, &err); |
2607 | |
|
2608 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); |
2609 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
2610 | 0 | pjsip_tx_data_dec_ref(tdata); |
2611 | 0 | tdata->mod_data[mod_tsx_layer.mod.id] = NULL; |
2612 | 0 | tsx->pending_tx = NULL; |
2613 | 0 | } |
2614 | | |
2615 | | /* Check if transaction is terminated. */ |
2616 | 0 | if (status==PJ_SUCCESS && tsx->state == PJSIP_TSX_STATE_TERMINATED) |
2617 | 0 | status = tsx->transport_err; |
2618 | |
|
2619 | 0 | } else { |
2620 | |
|
2621 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_TRANSPORT; |
2622 | 0 | status = pjsip_endpt_send_response( tsx->endpt, &tsx->res_addr, |
2623 | 0 | tdata, tsx, |
2624 | 0 | &send_msg_callback); |
2625 | 0 | if (status == PJ_EPENDING) |
2626 | 0 | status = PJ_SUCCESS; |
2627 | 0 | if (status != PJ_SUCCESS) { |
2628 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_TRANSPORT); |
2629 | 0 | pj_grp_lock_dec_ref(tsx->grp_lock); |
2630 | 0 | pjsip_tx_data_dec_ref(tdata); |
2631 | 0 | tdata->mod_data[mod_tsx_layer.mod.id] = NULL; |
2632 | 0 | tsx->pending_tx = NULL; |
2633 | 0 | } |
2634 | | |
2635 | | /* Check if transaction is terminated. */ |
2636 | 0 | if (status==PJ_SUCCESS && tsx->state == PJSIP_TSX_STATE_TERMINATED) |
2637 | 0 | status = tsx->transport_err; |
2638 | |
|
2639 | 0 | } |
2640 | | |
2641 | |
|
2642 | 0 | return status; |
2643 | 0 | } |
2644 | | |
2645 | | |
2646 | | /* |
2647 | | * Manually retransmit the last messagewithout updating the transaction state. |
2648 | | */ |
2649 | | PJ_DEF(pj_status_t) pjsip_tsx_retransmit_no_state(pjsip_transaction *tsx, |
2650 | | pjsip_tx_data *tdata) |
2651 | 0 | { |
2652 | 0 | pj_status_t status; |
2653 | |
|
2654 | 0 | PJ_ASSERT_RETURN(tsx != NULL, PJ_EINVAL); |
2655 | | |
2656 | 0 | pj_grp_lock_acquire(tsx->grp_lock); |
2657 | 0 | if (tdata == NULL) { |
2658 | 0 | tdata = tsx->last_tx; |
2659 | 0 | pjsip_tx_data_add_ref(tdata); |
2660 | 0 | } |
2661 | 0 | status = tsx_send_msg(tsx, tdata); |
2662 | 0 | pj_grp_lock_release(tsx->grp_lock); |
2663 | | |
2664 | | /* Only decrement reference counter when it returns success. |
2665 | | * (This is the specification from the .PDF design document). |
2666 | | */ |
2667 | 0 | if (status == PJ_SUCCESS) { |
2668 | 0 | pjsip_tx_data_dec_ref(tdata); |
2669 | 0 | } |
2670 | | |
2671 | 0 | return status; |
2672 | 0 | } |
2673 | | |
2674 | | |
2675 | | /* |
2676 | | * Retransmit last message sent. |
2677 | | */ |
2678 | | static void tsx_resched_retransmission( pjsip_transaction *tsx ) |
2679 | 0 | { |
2680 | 0 | pj_uint32_t msec_time; |
2681 | |
|
2682 | 0 | pj_assert((tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) == 0); |
2683 | |
|
2684 | 0 | if (tsx->role==PJSIP_ROLE_UAC && tsx->status_code >= 100) |
2685 | 0 | msec_time = pjsip_cfg()->tsx.t2; |
2686 | 0 | else |
2687 | 0 | msec_time = (1 << (tsx->retransmit_count)) * pjsip_cfg()->tsx.t1; |
2688 | |
|
2689 | 0 | if (tsx->role == PJSIP_ROLE_UAC) { |
2690 | 0 | pj_assert(tsx->status_code < 200); |
2691 | | /* Retransmission for non-INVITE transaction caps-off at T2 */ |
2692 | 0 | if (msec_time > pjsip_cfg()->tsx.t2 && |
2693 | 0 | tsx->method.id != PJSIP_INVITE_METHOD) |
2694 | 0 | { |
2695 | 0 | msec_time = pjsip_cfg()->tsx.t2; |
2696 | 0 | } |
2697 | 0 | } else { |
2698 | | /* For UAS, this can be retransmission of 2xx response for INVITE |
2699 | | * or non-100 1xx response. |
2700 | | */ |
2701 | 0 | if (tsx->status_code < 200) { |
2702 | | /* non-100 1xx retransmission is at 60 seconds */ |
2703 | 0 | msec_time = PJSIP_TSX_1XX_RETRANS_DELAY * 1000; |
2704 | 0 | } else { |
2705 | | /* Retransmission of INVITE final response also caps-off at T2 */ |
2706 | 0 | pj_assert(tsx->status_code >= 200); |
2707 | 0 | if (msec_time > pjsip_cfg()->tsx.t2) |
2708 | 0 | msec_time = pjsip_cfg()->tsx.t2; |
2709 | 0 | } |
2710 | 0 | } |
2711 | |
|
2712 | 0 | if (msec_time != 0) { |
2713 | 0 | pj_time_val timeout; |
2714 | |
|
2715 | 0 | timeout.sec = msec_time / 1000; |
2716 | 0 | timeout.msec = msec_time % 1000; |
2717 | 0 | tsx_schedule_timer( tsx, &tsx->retransmit_timer, &timeout, |
2718 | 0 | RETRANSMIT_TIMER); |
2719 | 0 | } |
2720 | 0 | } |
2721 | | |
2722 | | /* |
2723 | | * Retransmit last message sent. |
2724 | | */ |
2725 | | static pj_status_t tsx_retransmit( pjsip_transaction *tsx, int resched) |
2726 | 0 | { |
2727 | 0 | pj_status_t status; |
2728 | |
|
2729 | 0 | if (resched && pj_timer_entry_running(&tsx->retransmit_timer)) { |
2730 | | /* We've been asked to reschedule but the timer is already rerunning. |
2731 | | * This can only happen in a race condition where, between removing |
2732 | | * this retransmit timer from the heap and actually scheduling it, |
2733 | | * another thread has got in and rescheduled the timer itself. In |
2734 | | * this scenario, the transmission has already happened and so we |
2735 | | * should just quit out immediately, without either resending the |
2736 | | * message or restarting the timer. |
2737 | | */ |
2738 | 0 | return PJ_SUCCESS; |
2739 | 0 | } |
2740 | | |
2741 | 0 | PJ_ASSERT_RETURN(tsx->last_tx!=NULL, PJ_EBUG); |
2742 | | |
2743 | | /* If max retransmission count is reached, put it as timeout */ |
2744 | 0 | if (max_retrans_count >= 0 && |
2745 | 0 | tsx->retransmit_count >= max_retrans_count && |
2746 | 0 | tsx->last_tx->msg->type == PJSIP_REQUEST_MSG) |
2747 | 0 | { |
2748 | 0 | pj_time_val timeout = { 0, 0 }; |
2749 | |
|
2750 | 0 | PJ_LOG(3,(tsx->obj_name, |
2751 | 0 | "Stop retransmiting %s, max retrans %d reached, " |
2752 | 0 | "tsx set as timeout", |
2753 | 0 | pjsip_tx_data_get_info(tsx->last_tx), |
2754 | 0 | tsx->retransmit_count)); |
2755 | |
|
2756 | 0 | lock_timer(tsx); |
2757 | 0 | tsx_cancel_timer( tsx, &tsx->timeout_timer ); |
2758 | 0 | tsx_schedule_timer(tsx, &tsx->timeout_timer, &timeout, TIMEOUT_TIMER); |
2759 | 0 | unlock_timer(tsx); |
2760 | 0 | return PJ_SUCCESS; |
2761 | 0 | } |
2762 | | |
2763 | 0 | PJ_LOG(5,(tsx->obj_name, "Retransmiting %s, count=%d, restart?=%d", |
2764 | 0 | pjsip_tx_data_get_info(tsx->last_tx), |
2765 | 0 | tsx->retransmit_count, resched)); |
2766 | |
|
2767 | 0 | ++tsx->retransmit_count; |
2768 | | |
2769 | | /* Restart timer T1 first before sending the message to ensure that |
2770 | | * retransmission timer is not engaged when loop transport is used. |
2771 | | */ |
2772 | 0 | if (resched) { |
2773 | 0 | pj_assert(tsx->state != PJSIP_TSX_STATE_CONFIRMED); |
2774 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { |
2775 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; |
2776 | 0 | } else { |
2777 | 0 | tsx_resched_retransmission(tsx); |
2778 | 0 | } |
2779 | 0 | } |
2780 | |
|
2781 | 0 | status = tsx_send_msg( tsx, tsx->last_tx); |
2782 | 0 | if (status != PJ_SUCCESS) { |
2783 | 0 | return status; |
2784 | 0 | } |
2785 | | |
2786 | | /* Cancel retransmission timer if transport is pending. */ |
2787 | 0 | if (resched && (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT)) |
2788 | 0 | { |
2789 | 0 | tsx_cancel_timer( tsx, &tsx->retransmit_timer ); |
2790 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; |
2791 | 0 | } |
2792 | |
|
2793 | 0 | return PJ_SUCCESS; |
2794 | 0 | } |
2795 | | |
2796 | | static void tsx_update_transport( pjsip_transaction *tsx, |
2797 | | pjsip_transport *tp) |
2798 | 0 | { |
2799 | 0 | pj_assert(tsx); |
2800 | |
|
2801 | 0 | if (tsx->transport) { |
2802 | 0 | if (tsx->tp_st_key) { |
2803 | 0 | pjsip_transport_remove_state_listener(tsx->transport, |
2804 | 0 | tsx->tp_st_key, tsx); |
2805 | 0 | } |
2806 | 0 | pjsip_transport_dec_ref( tsx->transport ); |
2807 | 0 | tsx->transport = NULL; |
2808 | 0 | } |
2809 | |
|
2810 | 0 | if (tp) { |
2811 | 0 | tsx->transport = tp; |
2812 | 0 | pjsip_transport_add_ref(tp); |
2813 | 0 | pjsip_transport_add_state_listener(tp, &tsx_tp_state_callback, tsx, |
2814 | 0 | &tsx->tp_st_key); |
2815 | 0 | if (tp->is_shutdown || tp->is_destroying) { |
2816 | 0 | pjsip_transport_state_info info; |
2817 | |
|
2818 | 0 | pj_bzero(&info, sizeof(info)); |
2819 | 0 | info.user_data = tsx; |
2820 | 0 | info.status = PJSIP_SC_TSX_TRANSPORT_ERROR; |
2821 | 0 | tsx_tp_state_callback(tp, PJSIP_TP_STATE_DISCONNECTED, &info); |
2822 | 0 | } |
2823 | 0 | } |
2824 | 0 | } |
2825 | | |
2826 | | /* |
2827 | | * Handler for events in state Null. |
2828 | | */ |
2829 | | static pj_status_t tsx_on_state_null( pjsip_transaction *tsx, |
2830 | | pjsip_event *event ) |
2831 | 0 | { |
2832 | 0 | pj_status_t status; |
2833 | |
|
2834 | 0 | pj_assert(tsx->state == PJSIP_TSX_STATE_NULL); |
2835 | |
|
2836 | 0 | if (tsx->role == PJSIP_ROLE_UAS) { |
2837 | | |
2838 | | /* Set state to Trying. */ |
2839 | 0 | pj_assert(event->type == PJSIP_EVENT_RX_MSG && |
2840 | 0 | event->body.rx_msg.rdata->msg_info.msg->type == |
2841 | 0 | PJSIP_REQUEST_MSG); |
2842 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TRYING, PJSIP_EVENT_RX_MSG, |
2843 | 0 | event->body.rx_msg.rdata, 0); |
2844 | |
|
2845 | 0 | } else { |
2846 | 0 | pjsip_tx_data *tdata; |
2847 | | |
2848 | | /* Must be transmit event. |
2849 | | * You may got this assertion when using loop transport with delay |
2850 | | * set to zero. That would cause on_rx_response() callback to be |
2851 | | * called before tsx_send_msg() has completed. |
2852 | | */ |
2853 | 0 | PJ_ASSERT_RETURN(event->type == PJSIP_EVENT_TX_MSG, PJ_EBUG); |
2854 | | |
2855 | | /* Get the txdata */ |
2856 | 0 | tdata = event->body.tx_msg.tdata; |
2857 | | |
2858 | | /* Save the message for retransmission. */ |
2859 | 0 | if (tsx->last_tx && tsx->last_tx != tdata) { |
2860 | 0 | pjsip_tx_data_dec_ref(tsx->last_tx); |
2861 | 0 | tsx->last_tx = NULL; |
2862 | 0 | } |
2863 | 0 | if (tsx->last_tx != tdata) { |
2864 | 0 | tsx->last_tx = tdata; |
2865 | 0 | pjsip_tx_data_add_ref(tdata); |
2866 | 0 | } |
2867 | | |
2868 | | /* Send the message. */ |
2869 | 0 | status = tsx_send_msg( tsx, tdata); |
2870 | 0 | if (status != PJ_SUCCESS) { |
2871 | 0 | return status; |
2872 | 0 | } |
2873 | | |
2874 | | /* Start Timer B (or called timer F for non-INVITE) for transaction |
2875 | | * timeout. |
2876 | | */ |
2877 | 0 | lock_timer(tsx); |
2878 | 0 | tsx_cancel_timer( tsx, &tsx->timeout_timer ); |
2879 | 0 | tsx_schedule_timer( tsx, &tsx->timeout_timer, &timeout_timer_val, |
2880 | 0 | TIMEOUT_TIMER); |
2881 | 0 | unlock_timer(tsx); |
2882 | | |
2883 | | /* Start Timer A (or timer E) for retransmission only if unreliable |
2884 | | * transport is being used. |
2885 | | */ |
2886 | 0 | if (!tsx->is_reliable) { |
2887 | 0 | tsx->retransmit_count = 0; |
2888 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { |
2889 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; |
2890 | 0 | } else { |
2891 | 0 | tsx_schedule_timer(tsx, &tsx->retransmit_timer, |
2892 | 0 | &t1_timer_val, RETRANSMIT_TIMER); |
2893 | 0 | } |
2894 | 0 | } |
2895 | | |
2896 | | /* Move state. */ |
2897 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_CALLING, |
2898 | 0 | PJSIP_EVENT_TX_MSG, tdata, 0); |
2899 | 0 | } |
2900 | | |
2901 | 0 | return PJ_SUCCESS; |
2902 | 0 | } |
2903 | | |
2904 | | |
2905 | | /* |
2906 | | * State Calling is for UAC after it sends request but before any responses |
2907 | | * is received. |
2908 | | */ |
2909 | | static pj_status_t tsx_on_state_calling( pjsip_transaction *tsx, |
2910 | | pjsip_event *event ) |
2911 | 0 | { |
2912 | 0 | pj_assert(tsx->state == PJSIP_TSX_STATE_CALLING); |
2913 | 0 | pj_assert(tsx->role == PJSIP_ROLE_UAC); |
2914 | |
|
2915 | 0 | if (event->type == PJSIP_EVENT_TIMER && |
2916 | 0 | event->body.timer.entry == &tsx->retransmit_timer) |
2917 | 0 | { |
2918 | 0 | pj_status_t status; |
2919 | | |
2920 | | /* Retransmit the request. */ |
2921 | 0 | status = tsx_retransmit( tsx, 1 ); |
2922 | 0 | if (status != PJ_SUCCESS) { |
2923 | 0 | return status; |
2924 | 0 | } |
2925 | |
|
2926 | 0 | } else if (event->type == PJSIP_EVENT_TIMER && |
2927 | 0 | event->body.timer.entry == &tsx->timeout_timer) |
2928 | 0 | { |
2929 | | /* Cancel retransmission timer. */ |
2930 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
2931 | |
|
2932 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); |
2933 | | |
2934 | | /* Set status code */ |
2935 | 0 | tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL); |
2936 | | |
2937 | | /* Inform TU. */ |
2938 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
2939 | 0 | PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0); |
2940 | | |
2941 | | /* Transaction is destroyed */ |
2942 | | //return PJSIP_ETSXDESTROYED; |
2943 | |
|
2944 | 0 | } else if (event->type == PJSIP_EVENT_RX_MSG) { |
2945 | 0 | pjsip_msg *msg; |
2946 | 0 | int code; |
2947 | | |
2948 | | /* Get message instance */ |
2949 | 0 | msg = event->body.rx_msg.rdata->msg_info.msg; |
2950 | | |
2951 | | /* Better be a response message. */ |
2952 | 0 | if (msg->type != PJSIP_RESPONSE_MSG) |
2953 | 0 | return PJSIP_ENOTRESPONSEMSG; |
2954 | | |
2955 | 0 | code = msg->line.status.code; |
2956 | | |
2957 | | /* If the response is final, cancel both retransmission and timeout |
2958 | | * timer. |
2959 | | */ |
2960 | 0 | if (code >= 200) { |
2961 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
2962 | |
|
2963 | 0 | if (tsx->timeout_timer.id != 0) { |
2964 | 0 | lock_timer(tsx); |
2965 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
2966 | 0 | unlock_timer(tsx); |
2967 | 0 | } |
2968 | |
|
2969 | 0 | } else { |
2970 | | /* Cancel retransmit timer (for non-INVITE transaction, the |
2971 | | * retransmit timer will be rescheduled at T2. |
2972 | | */ |
2973 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
2974 | | |
2975 | | /* For provisional response, only cancel retransmit when this |
2976 | | * is an INVITE transaction. For non-INVITE, section 17.1.2.1 |
2977 | | * of RFC 3261 says that: |
2978 | | * - retransmit timer is set to T2 |
2979 | | * - timeout timer F is not deleted. |
2980 | | */ |
2981 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
2982 | | |
2983 | | /* Cancel timeout timer */ |
2984 | 0 | lock_timer(tsx); |
2985 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
2986 | 0 | unlock_timer(tsx); |
2987 | |
|
2988 | 0 | } else { |
2989 | 0 | if (!tsx->is_reliable) { |
2990 | 0 | tsx_schedule_timer(tsx, &tsx->retransmit_timer, |
2991 | 0 | &t2_timer_val, RETRANSMIT_TIMER); |
2992 | 0 | } |
2993 | 0 | } |
2994 | 0 | } |
2995 | | |
2996 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); |
2997 | | |
2998 | | |
2999 | | /* Discard retransmission message if it is not INVITE. |
3000 | | * The INVITE tdata is needed in case we have to generate ACK for |
3001 | | * the final response. |
3002 | | */ |
3003 | | /* Keep last_tx for authorization. */ |
3004 | | //blp: always keep last_tx until transaction is destroyed |
3005 | | //code = msg->line.status.code; |
3006 | | //if (tsx->method.id != PJSIP_INVITE_METHOD && code!=401 && code!=407) { |
3007 | | // pjsip_tx_data_dec_ref(tsx->last_tx); |
3008 | | // tsx->last_tx = NULL; |
3009 | | //} |
3010 | | |
3011 | | /* Processing is similar to state Proceeding. */ |
3012 | 0 | tsx_on_state_proceeding_uac( tsx, event); |
3013 | |
|
3014 | 0 | } else { |
3015 | 0 | pj_assert(!"Unexpected event"); |
3016 | 0 | return PJ_EBUG; |
3017 | 0 | } |
3018 | | |
3019 | 0 | return PJ_SUCCESS; |
3020 | 0 | } |
3021 | | |
3022 | | |
3023 | | /* |
3024 | | * State Trying is for UAS after it received request but before any responses |
3025 | | * is sent. |
3026 | | * Note: this is different than RFC3261, which can use Trying state for |
3027 | | * non-INVITE client transaction (bug in RFC?). |
3028 | | */ |
3029 | | static pj_status_t tsx_on_state_trying( pjsip_transaction *tsx, |
3030 | | pjsip_event *event) |
3031 | 0 | { |
3032 | 0 | pj_status_t status; |
3033 | |
|
3034 | 0 | pj_assert(tsx->state == PJSIP_TSX_STATE_TRYING); |
3035 | | |
3036 | | /* This state is only for UAS */ |
3037 | 0 | pj_assert(tsx->role == PJSIP_ROLE_UAS); |
3038 | | |
3039 | | /* Better be transmission of response message. |
3040 | | * If we've got request retransmission, this means that the TU hasn't |
3041 | | * transmitted any responses within 500 ms, which is not allowed. If |
3042 | | * this happens, just ignore the event (we couldn't retransmit last |
3043 | | * response because we haven't sent any!). |
3044 | | */ |
3045 | 0 | if (event->type != PJSIP_EVENT_TX_MSG) { |
3046 | 0 | return PJ_SUCCESS; |
3047 | 0 | } |
3048 | | |
3049 | | /* The rest of the processing of the event is exactly the same as in |
3050 | | * "Proceeding" state. |
3051 | | */ |
3052 | 0 | status = tsx_on_state_proceeding_uas( tsx, event); |
3053 | | |
3054 | | /* Inform the TU of the state transision if state is still State_Trying */ |
3055 | 0 | if (status==PJ_SUCCESS && tsx->state == PJSIP_TSX_STATE_TRYING) { |
3056 | |
|
3057 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, |
3058 | 0 | PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata, 0); |
3059 | |
|
3060 | 0 | } |
3061 | |
|
3062 | 0 | return status; |
3063 | 0 | } |
3064 | | |
3065 | | |
3066 | | /* |
3067 | | * Handler for events in Proceeding for UAS |
3068 | | * This state happens after the TU sends provisional response. |
3069 | | */ |
3070 | | static pj_status_t tsx_on_state_proceeding_uas( pjsip_transaction *tsx, |
3071 | | pjsip_event *event) |
3072 | 0 | { |
3073 | 0 | pj_assert(tsx->state == PJSIP_TSX_STATE_PROCEEDING || |
3074 | 0 | tsx->state == PJSIP_TSX_STATE_TRYING); |
3075 | | |
3076 | | /* This state is only for UAS. */ |
3077 | 0 | pj_assert(tsx->role == PJSIP_ROLE_UAS); |
3078 | | |
3079 | | /* Receive request retransmission. */ |
3080 | 0 | if (event->type == PJSIP_EVENT_RX_MSG) { |
3081 | |
|
3082 | 0 | pj_status_t status; |
3083 | | |
3084 | | /* Must have last response sent. */ |
3085 | 0 | PJ_ASSERT_RETURN(tsx->last_tx != NULL, PJ_EBUG); |
3086 | | |
3087 | | /* Send last response */ |
3088 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { |
3089 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_SEND; |
3090 | 0 | } else { |
3091 | 0 | status = tsx_send_msg(tsx, tsx->last_tx); |
3092 | 0 | if (status != PJ_SUCCESS) |
3093 | 0 | return status; |
3094 | 0 | } |
3095 | | |
3096 | 0 | } else if (event->type == PJSIP_EVENT_TX_MSG ) { |
3097 | 0 | pjsip_tx_data *tdata = event->body.tx_msg.tdata; |
3098 | 0 | pj_status_t status; |
3099 | | |
3100 | | /* The TU sends response message to the request. Save this message so |
3101 | | * that we can retransmit the last response in case we receive request |
3102 | | * retransmission. |
3103 | | */ |
3104 | 0 | pjsip_msg *msg = tdata->msg; |
3105 | | |
3106 | | /* This can only be a response message. */ |
3107 | 0 | PJ_ASSERT_RETURN(msg->type==PJSIP_RESPONSE_MSG, PJSIP_ENOTRESPONSEMSG); |
3108 | | |
3109 | | /* Update last status */ |
3110 | 0 | tsx_set_status_code(tsx, msg->line.status.code, |
3111 | 0 | &msg->line.status.reason); |
3112 | | |
3113 | | /* Discard the saved last response (it will be updated later as |
3114 | | * necessary). |
3115 | | */ |
3116 | 0 | if (tsx->last_tx && tsx->last_tx != tdata) { |
3117 | 0 | pjsip_tx_data_dec_ref( tsx->last_tx ); |
3118 | 0 | tsx->last_tx = NULL; |
3119 | 0 | } |
3120 | | |
3121 | | /* Send the message. */ |
3122 | 0 | status = tsx_send_msg(tsx, tdata); |
3123 | 0 | if (status != PJ_SUCCESS) { |
3124 | 0 | return status; |
3125 | 0 | } |
3126 | | |
3127 | | // Update To tag header for RFC2543 transaction. |
3128 | | // TODO: |
3129 | | |
3130 | | /* Update transaction state */ |
3131 | 0 | if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 100)) { |
3132 | |
|
3133 | 0 | if (tsx->last_tx != tdata) { |
3134 | 0 | tsx->last_tx = tdata; |
3135 | 0 | pjsip_tx_data_add_ref( tdata ); |
3136 | 0 | } |
3137 | |
|
3138 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, |
3139 | 0 | PJSIP_EVENT_TX_MSG, tdata, 0 ); |
3140 | | |
3141 | | /* Retransmit provisional response every 1 minute if this is |
3142 | | * an INVITE provisional response greater than 100. |
3143 | | */ |
3144 | 0 | if (PJSIP_TSX_1XX_RETRANS_DELAY > 0 && |
3145 | 0 | tsx->method.id==PJSIP_INVITE_METHOD && tsx->status_code>100) |
3146 | 0 | { |
3147 | | |
3148 | | /* Stop 1xx retransmission timer, if any */ |
3149 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
3150 | | |
3151 | | /* Schedule retransmission */ |
3152 | 0 | tsx->retransmit_count = 0; |
3153 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { |
3154 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; |
3155 | 0 | } else { |
3156 | 0 | pj_time_val delay = {PJSIP_TSX_1XX_RETRANS_DELAY, 0}; |
3157 | 0 | tsx_schedule_timer( tsx, &tsx->retransmit_timer, &delay, |
3158 | 0 | RETRANSMIT_TIMER); |
3159 | 0 | } |
3160 | 0 | } |
3161 | |
|
3162 | 0 | } else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200)) { |
3163 | | |
3164 | | /* Stop 1xx retransmission timer, if any */ |
3165 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
3166 | |
|
3167 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD && tsx->handle_200resp==0) { |
3168 | | |
3169 | | /* 2xx class message is not saved, because retransmission |
3170 | | * is handled by TU. |
3171 | | */ |
3172 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
3173 | 0 | PJSIP_EVENT_TX_MSG, tdata, 0 ); |
3174 | | |
3175 | | /* Transaction is destroyed. */ |
3176 | | //return PJSIP_ETSXDESTROYED; |
3177 | |
|
3178 | 0 | } else { |
3179 | 0 | pj_time_val timeout; |
3180 | |
|
3181 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3182 | 0 | tsx->retransmit_count = 0; |
3183 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { |
3184 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; |
3185 | 0 | } else { |
3186 | 0 | tsx_schedule_timer( tsx, &tsx->retransmit_timer, |
3187 | 0 | &t1_timer_val, RETRANSMIT_TIMER); |
3188 | 0 | } |
3189 | 0 | } |
3190 | | |
3191 | | /* Save last response sent for retransmission when request |
3192 | | * retransmission is received. |
3193 | | */ |
3194 | 0 | if (tsx->last_tx != tdata) { |
3195 | 0 | tsx->last_tx = tdata; |
3196 | 0 | pjsip_tx_data_add_ref(tdata); |
3197 | 0 | } |
3198 | | |
3199 | | /* Setup timeout timer: */ |
3200 | | |
3201 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3202 | | |
3203 | | /* Start Timer H at 64*T1 for INVITE server transaction, |
3204 | | * regardless of transport. |
3205 | | */ |
3206 | 0 | timeout = timeout_timer_val; |
3207 | | |
3208 | 0 | } else if (!tsx->is_reliable) { |
3209 | | |
3210 | | /* For non-INVITE, start timer J at 64*T1 for unreliable |
3211 | | * transport. |
3212 | | */ |
3213 | 0 | timeout = timeout_timer_val; |
3214 | | |
3215 | 0 | } else { |
3216 | | |
3217 | | /* Transaction terminates immediately for non-INVITE when |
3218 | | * reliable transport is used. |
3219 | | */ |
3220 | 0 | timeout.sec = timeout.msec = 0; |
3221 | 0 | } |
3222 | |
|
3223 | 0 | lock_timer(tsx); |
3224 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
3225 | 0 | tsx_schedule_timer( tsx, &tsx->timeout_timer, |
3226 | 0 | &timeout, TIMEOUT_TIMER); |
3227 | 0 | unlock_timer(tsx); |
3228 | | |
3229 | | /* Set state to "Completed" */ |
3230 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, |
3231 | 0 | PJSIP_EVENT_TX_MSG, tdata, 0 ); |
3232 | 0 | } |
3233 | |
|
3234 | 0 | } else if (tsx->status_code >= 300) { |
3235 | | |
3236 | | /* Stop 1xx retransmission timer, if any */ |
3237 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
3238 | | |
3239 | | /* 3xx-6xx class message causes transaction to move to |
3240 | | * "Completed" state. |
3241 | | */ |
3242 | 0 | if (tsx->last_tx != tdata) { |
3243 | 0 | tsx->last_tx = tdata; |
3244 | 0 | pjsip_tx_data_add_ref( tdata ); |
3245 | 0 | } |
3246 | | |
3247 | | /* For INVITE, start timer H for transaction termination |
3248 | | * regardless whether transport is reliable or not. |
3249 | | * For non-INVITE, start timer J with the value of 64*T1 for |
3250 | | * non-reliable transports, and zero for reliable transports. |
3251 | | */ |
3252 | 0 | lock_timer(tsx); |
3253 | 0 | tsx_cancel_timer(tsx, &tsx->timeout_timer); |
3254 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3255 | | /* Start timer H for INVITE */ |
3256 | 0 | tsx_schedule_timer(tsx, &tsx->timeout_timer, |
3257 | 0 | &timeout_timer_val, TIMEOUT_TIMER); |
3258 | 0 | } else if (!tsx->is_reliable) { |
3259 | | /* Start timer J on 64*T1 seconds for non-INVITE */ |
3260 | 0 | tsx_schedule_timer(tsx, &tsx->timeout_timer, |
3261 | 0 | &timeout_timer_val, TIMEOUT_TIMER); |
3262 | 0 | } else { |
3263 | | /* Start timer J on zero seconds for non-INVITE */ |
3264 | 0 | pj_time_val zero_time = { 0, 0 }; |
3265 | 0 | tsx_schedule_timer(tsx, &tsx->timeout_timer, |
3266 | 0 | &zero_time, TIMEOUT_TIMER); |
3267 | 0 | } |
3268 | 0 | unlock_timer(tsx); |
3269 | | |
3270 | | /* For INVITE, if unreliable transport is used, retransmission |
3271 | | * timer G will be scheduled (retransmission). |
3272 | | */ |
3273 | 0 | if (!tsx->is_reliable) { |
3274 | 0 | pjsip_cseq_hdr *cseq = (pjsip_cseq_hdr*) |
3275 | 0 | pjsip_msg_find_hdr( msg, PJSIP_H_CSEQ, |
3276 | 0 | NULL); |
3277 | 0 | if (cseq->method.id == PJSIP_INVITE_METHOD) { |
3278 | 0 | tsx->retransmit_count = 0; |
3279 | 0 | if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) { |
3280 | 0 | tsx->transport_flag |= TSX_HAS_PENDING_RESCHED; |
3281 | 0 | } else { |
3282 | 0 | tsx_schedule_timer(tsx, &tsx->retransmit_timer, |
3283 | 0 | &t1_timer_val, RETRANSMIT_TIMER); |
3284 | 0 | } |
3285 | 0 | } |
3286 | 0 | } |
3287 | | |
3288 | | /* Inform TU */ |
3289 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, |
3290 | 0 | PJSIP_EVENT_TX_MSG, tdata, 0 ); |
3291 | |
|
3292 | 0 | } else { |
3293 | 0 | pj_assert(0); |
3294 | 0 | } |
3295 | | |
3296 | |
|
3297 | 0 | } else if (event->type == PJSIP_EVENT_TIMER && |
3298 | 0 | event->body.timer.entry == &tsx->retransmit_timer) { |
3299 | | |
3300 | | /* Retransmission timer elapsed. */ |
3301 | 0 | pj_status_t status; |
3302 | | |
3303 | | /* Must not be triggered while transport is pending. */ |
3304 | 0 | pj_assert((tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) == 0); |
3305 | | |
3306 | | /* Must have last response to retransmit. */ |
3307 | 0 | pj_assert(tsx->last_tx != NULL); |
3308 | | |
3309 | | /* Retransmit the last response. */ |
3310 | 0 | status = tsx_retransmit( tsx, 1 ); |
3311 | 0 | if (status != PJ_SUCCESS) { |
3312 | 0 | return status; |
3313 | 0 | } |
3314 | |
|
3315 | 0 | } else if (event->type == PJSIP_EVENT_TIMER && |
3316 | 0 | event->body.timer.entry == &tsx->timeout_timer) { |
3317 | | |
3318 | | /* Timeout timer. should not happen? */ |
3319 | 0 | pj_assert(!"Should not happen(?)"); |
3320 | |
|
3321 | 0 | tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL); |
3322 | |
|
3323 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
3324 | 0 | PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0); |
3325 | |
|
3326 | 0 | return PJ_EBUG; |
3327 | |
|
3328 | 0 | } else { |
3329 | 0 | pj_assert(!"Unexpected event"); |
3330 | 0 | return PJ_EBUG; |
3331 | 0 | } |
3332 | | |
3333 | 0 | return PJ_SUCCESS; |
3334 | 0 | } |
3335 | | |
3336 | | |
3337 | | /* |
3338 | | * Handler for events in Proceeding for UAC |
3339 | | * This state happens after provisional response(s) has been received from |
3340 | | * UAS. |
3341 | | */ |
3342 | | static pj_status_t tsx_on_state_proceeding_uac(pjsip_transaction *tsx, |
3343 | | pjsip_event *event) |
3344 | 0 | { |
3345 | |
|
3346 | 0 | pj_assert(tsx->state == PJSIP_TSX_STATE_PROCEEDING || |
3347 | 0 | tsx->state == PJSIP_TSX_STATE_CALLING); |
3348 | |
|
3349 | 0 | if (event->type != PJSIP_EVENT_TIMER) { |
3350 | 0 | pjsip_msg *msg; |
3351 | | |
3352 | | /* Must be incoming response, because we should not retransmit |
3353 | | * request once response has been received. |
3354 | | */ |
3355 | 0 | pj_assert(event->type == PJSIP_EVENT_RX_MSG); |
3356 | 0 | if (event->type != PJSIP_EVENT_RX_MSG) { |
3357 | 0 | return PJ_EINVALIDOP; |
3358 | 0 | } |
3359 | | |
3360 | 0 | msg = event->body.rx_msg.rdata->msg_info.msg; |
3361 | | |
3362 | | /* Must be a response message. */ |
3363 | 0 | if (msg->type != PJSIP_RESPONSE_MSG) { |
3364 | 0 | pj_assert(!"Expecting response message!"); |
3365 | 0 | return PJSIP_ENOTRESPONSEMSG; |
3366 | 0 | } |
3367 | | |
3368 | 0 | tsx_set_status_code(tsx, msg->line.status.code, |
3369 | 0 | &msg->line.status.reason); |
3370 | |
|
3371 | 0 | } else { |
3372 | 0 | if (event->body.timer.entry == &tsx->retransmit_timer) { |
3373 | | /* Retransmit message. */ |
3374 | 0 | pj_status_t status; |
3375 | |
|
3376 | 0 | status = tsx_retransmit( tsx, 1 ); |
3377 | | |
3378 | 0 | return status; |
3379 | |
|
3380 | 0 | } else { |
3381 | 0 | tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL); |
3382 | 0 | } |
3383 | 0 | } |
3384 | | |
3385 | 0 | if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 100)) { |
3386 | | |
3387 | | /* Inform the message to TU. */ |
3388 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, |
3389 | 0 | PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0 ); |
3390 | |
|
3391 | 0 | } else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code,200)) { |
3392 | | |
3393 | | /* Stop timeout timer B/F. */ |
3394 | 0 | lock_timer(tsx); |
3395 | 0 | tsx_cancel_timer( tsx, &tsx->timeout_timer ); |
3396 | 0 | unlock_timer(tsx); |
3397 | | |
3398 | | /* For INVITE, the state moves to Terminated state (because ACK is |
3399 | | * handled in TU). For non-INVITE, state moves to Completed. |
3400 | | */ |
3401 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3402 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
3403 | 0 | PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0 ); |
3404 | | //return PJSIP_ETSXDESTROYED; |
3405 | |
|
3406 | 0 | } else { |
3407 | 0 | pj_time_val timeout; |
3408 | | |
3409 | | /* For unreliable transport, start timer D (for INVITE) or |
3410 | | * timer K for non-INVITE. */ |
3411 | 0 | if (!tsx->is_reliable) { |
3412 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3413 | 0 | timeout = td_timer_val; |
3414 | 0 | } else { |
3415 | 0 | timeout = t4_timer_val; |
3416 | 0 | } |
3417 | 0 | } else { |
3418 | 0 | timeout.sec = timeout.msec = 0; |
3419 | 0 | } |
3420 | 0 | lock_timer(tsx); |
3421 | 0 | tsx_schedule_timer( tsx, &tsx->timeout_timer, |
3422 | 0 | &timeout, TIMEOUT_TIMER); |
3423 | 0 | unlock_timer(tsx); |
3424 | | |
3425 | | /* Cancel retransmission timer */ |
3426 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
3427 | | |
3428 | | /* Move state to Completed, inform TU. */ |
3429 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, |
3430 | 0 | PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0 ); |
3431 | 0 | } |
3432 | |
|
3433 | 0 | } else if (event->type == PJSIP_EVENT_TIMER && |
3434 | 0 | event->body.timer.entry == &tsx->timeout_timer) { |
3435 | | |
3436 | | /* Inform TU. */ |
3437 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
3438 | 0 | PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0); |
3439 | | |
3440 | |
|
3441 | 0 | } else if (tsx->status_code >= 300 && tsx->status_code <= 699) { |
3442 | | |
3443 | |
|
3444 | | #if 0 |
3445 | | /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ |
3446 | | /* |
3447 | | * This is the old code; it's broken for authentication. |
3448 | | */ |
3449 | | pj_time_val timeout; |
3450 | | pj_status_t status; |
3451 | | |
3452 | | /* Stop timer B. */ |
3453 | | tsx_cancel_timer( tsx, &tsx->timeout_timer ); |
3454 | | |
3455 | | /* Generate and send ACK for INVITE. */ |
3456 | | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3457 | | pjsip_tx_data *ack; |
3458 | | |
3459 | | status = pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx, |
3460 | | event->body.rx_msg.rdata, |
3461 | | &ack); |
3462 | | if (status != PJ_SUCCESS) |
3463 | | return status; |
3464 | | |
3465 | | if (ack != tsx->last_tx) { |
3466 | | pjsip_tx_data_dec_ref(tsx->last_tx); |
3467 | | tsx->last_tx = ack; |
3468 | | } |
3469 | | |
3470 | | status = tsx_send_msg( tsx, tsx->last_tx); |
3471 | | if (status != PJ_SUCCESS) { |
3472 | | return status; |
3473 | | } |
3474 | | } |
3475 | | |
3476 | | /* Start Timer D with TD/T4 timer if unreliable transport is used. */ |
3477 | | if (!tsx->is_reliable) { |
3478 | | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3479 | | timeout = td_timer_val; |
3480 | | } else { |
3481 | | timeout = t4_timer_val; |
3482 | | } |
3483 | | } else { |
3484 | | timeout.sec = timeout.msec = 0; |
3485 | | } |
3486 | | tsx_schedule_timer( tsx, &tsx->timeout_timer, &timeout, TIMEOUT_TIMER); |
3487 | | |
3488 | | /* Inform TU. |
3489 | | * blp: You might be tempted to move this notification before |
3490 | | * sending ACK, but I think you shouldn't. Better set-up |
3491 | | * everything before calling tsx_user's callback to avoid |
3492 | | * mess up. |
3493 | | */ |
3494 | | tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, |
3495 | | PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata ); |
3496 | | |
3497 | | /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ |
3498 | | #endif |
3499 | | |
3500 | | /* New code, taken from 0.2.9.x branch */ |
3501 | 0 | pj_time_val timeout; |
3502 | 0 | pjsip_tx_data *ack_tdata = NULL; |
3503 | | |
3504 | | /* Cancel retransmission timer */ |
3505 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
3506 | | |
3507 | | /* Stop timer B. */ |
3508 | 0 | lock_timer(tsx); |
3509 | 0 | tsx_cancel_timer( tsx, &tsx->timeout_timer ); |
3510 | 0 | unlock_timer(tsx); |
3511 | | |
3512 | | /* Generate and send ACK (for INVITE) */ |
3513 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3514 | 0 | pj_status_t status; |
3515 | |
|
3516 | 0 | status = pjsip_endpt_create_ack( tsx->endpt, tsx->last_tx, |
3517 | 0 | event->body.rx_msg.rdata, |
3518 | 0 | &ack_tdata); |
3519 | 0 | if (status != PJ_SUCCESS) |
3520 | 0 | return status; |
3521 | | |
3522 | 0 | status = tsx_send_msg( tsx, ack_tdata); |
3523 | 0 | if (status != PJ_SUCCESS) |
3524 | 0 | return status; |
3525 | |
|
3526 | 0 | } else if ((tsx->method.id == PJSIP_BYE_METHOD) && |
3527 | 0 | (tsx->status_code == PJSIP_SC_REQUEST_TIMEOUT || |
3528 | 0 | tsx->status_code == PJSIP_SC_CALL_TSX_DOES_NOT_EXIST)) |
3529 | 0 | { |
3530 | | /* RFC 3261 15.1.1: |
3531 | | * If the response for the BYE is a 481 (Call/Transaction Does |
3532 | | * Not Exist) or a 408 (Request Timeout) or no response at all |
3533 | | * is received for the BYE (that is, a timeout is returned by |
3534 | | * the client transaction), the UAC MUST consider the |
3535 | | * session and the dialog terminated. |
3536 | | */ |
3537 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
3538 | 0 | PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0 ); |
3539 | 0 | return PJ_SUCCESS; |
3540 | 0 | } |
3541 | | |
3542 | | /* Inform TU. */ |
3543 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, |
3544 | 0 | PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0); |
3545 | | |
3546 | | /* Generate and send ACK for INVITE. */ |
3547 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3548 | 0 | if (ack_tdata != tsx->last_tx) { |
3549 | 0 | pjsip_tx_data_dec_ref(tsx->last_tx); |
3550 | 0 | tsx->last_tx = ack_tdata; |
3551 | | |
3552 | | /* This is a bug. |
3553 | | tsx_send_msg() does NOT decrement tdata's reference counter, |
3554 | | so if we add the reference counter here, tdata will have |
3555 | | reference counter 2, causing it to leak. |
3556 | | pjsip_tx_data_add_ref(ack_tdata); |
3557 | | */ |
3558 | 0 | } |
3559 | 0 | } |
3560 | | |
3561 | | /* Start Timer D with TD/T4 timer if unreliable transport is used. */ |
3562 | | /* Note: tsx->transport may be NULL! */ |
3563 | 0 | if (!tsx->is_reliable) { |
3564 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3565 | 0 | timeout = td_timer_val; |
3566 | 0 | } else { |
3567 | 0 | timeout = t4_timer_val; |
3568 | 0 | } |
3569 | 0 | } else { |
3570 | 0 | timeout.sec = timeout.msec = 0; |
3571 | 0 | } |
3572 | 0 | lock_timer(tsx); |
3573 | | /* In the short period above timer may have been inserted |
3574 | | * by set_timeout() (by CANCEL). Cancel it if necessary. See: |
3575 | | * https://github.com/pjsip/pjproject/issues/1374 |
3576 | | */ |
3577 | 0 | tsx_cancel_timer( tsx, &tsx->timeout_timer ); |
3578 | 0 | tsx_schedule_timer( tsx, &tsx->timeout_timer, &timeout, |
3579 | 0 | TIMEOUT_TIMER); |
3580 | 0 | unlock_timer(tsx); |
3581 | |
|
3582 | 0 | } else { |
3583 | | // Shouldn't happen because there's no timer for this state. |
3584 | 0 | pj_assert(!"Unexpected event"); |
3585 | 0 | return PJ_EBUG; |
3586 | 0 | } |
3587 | | |
3588 | 0 | return PJ_SUCCESS; |
3589 | 0 | } |
3590 | | |
3591 | | |
3592 | | /* |
3593 | | * Handler for events in Completed state for UAS |
3594 | | */ |
3595 | | static pj_status_t tsx_on_state_completed_uas( pjsip_transaction *tsx, |
3596 | | pjsip_event *event) |
3597 | 0 | { |
3598 | 0 | pj_assert(tsx->state == PJSIP_TSX_STATE_COMPLETED); |
3599 | |
|
3600 | 0 | if (event->type == PJSIP_EVENT_RX_MSG) { |
3601 | 0 | pjsip_msg *msg = event->body.rx_msg.rdata->msg_info.msg; |
3602 | | |
3603 | | /* This must be a request message retransmission. */ |
3604 | 0 | if (msg->type != PJSIP_REQUEST_MSG) |
3605 | 0 | return PJSIP_ENOTREQUESTMSG; |
3606 | | |
3607 | | /* On receive request retransmission, retransmit last response. */ |
3608 | 0 | if (msg->line.req.method.id != PJSIP_ACK_METHOD) { |
3609 | 0 | pj_status_t status; |
3610 | |
|
3611 | 0 | status = tsx_retransmit( tsx, 0 ); |
3612 | 0 | if (status != PJ_SUCCESS) { |
3613 | 0 | return status; |
3614 | 0 | } |
3615 | |
|
3616 | 0 | } else { |
3617 | 0 | pj_time_val timeout; |
3618 | | |
3619 | | /* Process incoming ACK request. */ |
3620 | | |
3621 | | /* Verify that this is an INVITE transaction */ |
3622 | 0 | if (tsx->method.id != PJSIP_INVITE_METHOD) { |
3623 | 0 | PJ_LOG(2, (tsx->obj_name, |
3624 | 0 | "Received illegal ACK for %.*s transaction", |
3625 | 0 | (int)tsx->method.name.slen, |
3626 | 0 | tsx->method.name.ptr)); |
3627 | 0 | return PJSIP_EINVALIDMETHOD; |
3628 | 0 | } |
3629 | | |
3630 | | /* Cease retransmission. */ |
3631 | 0 | tsx_cancel_timer(tsx, &tsx->retransmit_timer); |
3632 | |
|
3633 | 0 | tsx->transport_flag &= ~(TSX_HAS_PENDING_RESCHED); |
3634 | | |
3635 | | /* Reschedule timeout timer. */ |
3636 | 0 | lock_timer(tsx); |
3637 | 0 | tsx_cancel_timer( tsx, &tsx->timeout_timer ); |
3638 | | |
3639 | | /* Timer I is T4 timer for unreliable transports, and |
3640 | | * zero seconds for reliable transports. |
3641 | | */ |
3642 | 0 | if (tsx->is_reliable) { |
3643 | 0 | timeout.sec = 0; |
3644 | 0 | timeout.msec = 0; |
3645 | 0 | } else { |
3646 | 0 | timeout.sec = t4_timer_val.sec; |
3647 | 0 | timeout.msec = t4_timer_val.msec; |
3648 | 0 | } |
3649 | 0 | tsx_schedule_timer( tsx, &tsx->timeout_timer, |
3650 | 0 | &timeout, TIMEOUT_TIMER); |
3651 | 0 | unlock_timer(tsx); |
3652 | | |
3653 | | /* Move state to "Confirmed" */ |
3654 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_CONFIRMED, |
3655 | 0 | PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0 ); |
3656 | 0 | } |
3657 | |
|
3658 | 0 | } else if (event->type == PJSIP_EVENT_TIMER) { |
3659 | |
|
3660 | 0 | if (event->body.timer.entry == &tsx->retransmit_timer) { |
3661 | | /* Retransmit message. */ |
3662 | 0 | pj_status_t status; |
3663 | |
|
3664 | 0 | status = tsx_retransmit( tsx, 1 ); |
3665 | 0 | if (status != PJ_SUCCESS) { |
3666 | 0 | return status; |
3667 | 0 | } |
3668 | |
|
3669 | 0 | } else { |
3670 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3671 | | |
3672 | | /* For INVITE, this means that ACK was never received. |
3673 | | * Set state to Terminated, and inform TU. |
3674 | | */ |
3675 | |
|
3676 | 0 | tsx_set_status_code(tsx, PJSIP_SC_TSX_TIMEOUT, NULL); |
3677 | |
|
3678 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
3679 | 0 | PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0 ); |
3680 | | |
3681 | | //return PJSIP_ETSXDESTROYED; |
3682 | |
|
3683 | 0 | } else { |
3684 | | /* Transaction terminated, it can now be deleted. */ |
3685 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
3686 | 0 | PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0 ); |
3687 | | //return PJSIP_ETSXDESTROYED; |
3688 | 0 | } |
3689 | 0 | } |
3690 | |
|
3691 | 0 | } else { |
3692 | 0 | PJ_ASSERT_RETURN(event->type == PJSIP_EVENT_TX_MSG, |
3693 | 0 | PJ_EINVALIDOP); |
3694 | | /* Ignore request to transmit a new message. */ |
3695 | 0 | if (event->body.tx_msg.tdata != tsx->last_tx) |
3696 | 0 | return PJ_EINVALIDOP; |
3697 | 0 | } |
3698 | | |
3699 | 0 | return PJ_SUCCESS; |
3700 | 0 | } |
3701 | | |
3702 | | |
3703 | | /* |
3704 | | * Handler for events in Completed state for UAC transaction. |
3705 | | */ |
3706 | | static pj_status_t tsx_on_state_completed_uac( pjsip_transaction *tsx, |
3707 | | pjsip_event *event) |
3708 | 0 | { |
3709 | 0 | pj_assert(tsx->state == PJSIP_TSX_STATE_COMPLETED); |
3710 | |
|
3711 | 0 | if (event->type == PJSIP_EVENT_TIMER) { |
3712 | | /* Ignore stray retransmit event |
3713 | | * https://github.com/pjsip/pjproject/issues/1766 |
3714 | | */ |
3715 | 0 | if (event->body.timer.entry != &tsx->timeout_timer) |
3716 | 0 | return PJ_SUCCESS; |
3717 | | |
3718 | | /* Move to Terminated state. */ |
3719 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
3720 | 0 | PJSIP_EVENT_TIMER, event->body.timer.entry, 0 ); |
3721 | | |
3722 | | /* Transaction has been destroyed. */ |
3723 | | //return PJSIP_ETSXDESTROYED; |
3724 | |
|
3725 | 0 | } else if (event->type == PJSIP_EVENT_RX_MSG) { |
3726 | 0 | if (tsx->method.id == PJSIP_INVITE_METHOD) { |
3727 | | /* On received of final response retransmission, retransmit the ACK. |
3728 | | * TU doesn't need to be informed. |
3729 | | */ |
3730 | 0 | pjsip_msg *msg = event->body.rx_msg.rdata->msg_info.msg; |
3731 | 0 | pj_assert(msg->type == PJSIP_RESPONSE_MSG); |
3732 | 0 | if (msg->type==PJSIP_RESPONSE_MSG && |
3733 | 0 | msg->line.status.code >= 200) |
3734 | 0 | { |
3735 | 0 | pj_status_t status; |
3736 | |
|
3737 | 0 | status = tsx_retransmit( tsx, 0 ); |
3738 | 0 | if (status != PJ_SUCCESS) { |
3739 | 0 | return status; |
3740 | 0 | } |
3741 | 0 | } else { |
3742 | | /* Very late retransmission of privisional response. */ |
3743 | 0 | pj_assert( msg->type == PJSIP_RESPONSE_MSG ); |
3744 | 0 | } |
3745 | 0 | } else { |
3746 | | /* Just drop the response. */ |
3747 | 0 | } |
3748 | |
|
3749 | 0 | } else { |
3750 | 0 | pj_assert(!"Unexpected event"); |
3751 | 0 | return PJ_EINVALIDOP; |
3752 | 0 | } |
3753 | | |
3754 | 0 | return PJ_SUCCESS; |
3755 | 0 | } |
3756 | | |
3757 | | |
3758 | | /* |
3759 | | * Handler for events in state Confirmed. |
3760 | | */ |
3761 | | static pj_status_t tsx_on_state_confirmed( pjsip_transaction *tsx, |
3762 | | pjsip_event *event) |
3763 | 0 | { |
3764 | 0 | pj_assert(tsx->state == PJSIP_TSX_STATE_CONFIRMED); |
3765 | | |
3766 | | /* This state is only for UAS for INVITE. */ |
3767 | 0 | pj_assert(tsx->role == PJSIP_ROLE_UAS); |
3768 | 0 | pj_assert(tsx->method.id == PJSIP_INVITE_METHOD); |
3769 | | |
3770 | | /* Absorb any ACK received. */ |
3771 | 0 | if (event->type == PJSIP_EVENT_RX_MSG) { |
3772 | |
|
3773 | 0 | pjsip_msg *msg = event->body.rx_msg.rdata->msg_info.msg; |
3774 | | |
3775 | | /* Only expecting request message. */ |
3776 | 0 | if (msg->type != PJSIP_REQUEST_MSG) |
3777 | 0 | return PJSIP_ENOTREQUESTMSG; |
3778 | | |
3779 | | /* Must be an ACK request or a late INVITE retransmission. */ |
3780 | 0 | pj_assert(msg->line.req.method.id == PJSIP_ACK_METHOD || |
3781 | 0 | msg->line.req.method.id == PJSIP_INVITE_METHOD); |
3782 | |
|
3783 | 0 | } else if (event->type == PJSIP_EVENT_TIMER) { |
3784 | | /* Ignore overlapped retransmit timer. |
3785 | | * https://github.com/pjsip/pjproject/issues/1746 |
3786 | | */ |
3787 | 0 | if (event->body.timer.entry == &tsx->retransmit_timer) { |
3788 | | /* Ignore */ |
3789 | 0 | } else { |
3790 | | /* Must be from timeout_timer_. */ |
3791 | 0 | pj_assert(event->body.timer.entry == &tsx->timeout_timer); |
3792 | | |
3793 | | /* Move to Terminated state. */ |
3794 | 0 | tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, |
3795 | 0 | PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0 ); |
3796 | | |
3797 | | /* Transaction has been destroyed. */ |
3798 | | //return PJSIP_ETSXDESTROYED; |
3799 | 0 | } |
3800 | 0 | } else { |
3801 | 0 | pj_assert(!"Unexpected event"); |
3802 | 0 | return PJ_EBUG; |
3803 | 0 | } |
3804 | | |
3805 | 0 | return PJ_SUCCESS; |
3806 | 0 | } |
3807 | | |
3808 | | |
3809 | | /* |
3810 | | * Handler for events in state Terminated. |
3811 | | */ |
3812 | | static pj_status_t tsx_on_state_terminated( pjsip_transaction *tsx, |
3813 | | pjsip_event *event) |
3814 | 0 | { |
3815 | 0 | pj_assert(tsx->state == PJSIP_TSX_STATE_TERMINATED); |
3816 | | |
3817 | | /* Ignore events other than timer. This used to be an assertion but |
3818 | | * events may genuinely arrive at this state. |
3819 | | */ |
3820 | 0 | if (event->type != PJSIP_EVENT_TIMER) { |
3821 | 0 | return PJ_EIGNORED; |
3822 | 0 | } |
3823 | | |
3824 | | /* Destroy this transaction */ |
3825 | 0 | tsx_set_state(tsx, PJSIP_TSX_STATE_DESTROYED, |
3826 | 0 | event->type, event->body.user.user1, 0 ); |
3827 | |
|
3828 | 0 | return PJ_SUCCESS; |
3829 | 0 | } |
3830 | | |
3831 | | |
3832 | | /* |
3833 | | * Handler for events in state Destroyed. |
3834 | | * Shouldn't happen! |
3835 | | */ |
3836 | | static pj_status_t tsx_on_state_destroyed(pjsip_transaction *tsx, |
3837 | | pjsip_event *event) |
3838 | 0 | { |
3839 | 0 | PJ_UNUSED_ARG(tsx); |
3840 | 0 | PJ_UNUSED_ARG(event); |
3841 | | |
3842 | | // See https://github.com/pjsip/pjproject/issues/1432 |
3843 | | //pj_assert(!"Not expecting any events!!"); |
3844 | |
|
3845 | 0 | return PJ_EIGNORED; |
3846 | 0 | } |
3847 | | |