blob: 1cb54fe3e52ffc90b01b9145eca6003562617de1 [file] [log] [blame]
Benny Prijono0a749f12005-10-31 21:02:30 +00001/* $Header: /pjproject-0.3/pjsip/src/pjsip_mod_ua/sip_dialog.c 27 10/14/05 12:23a Bennylp $ */
2#include <pjsip_mod_ua/sip_dialog.h>
3#include <pjsip_mod_ua/sip_ua.h>
4#include <pjsip_mod_ua/sip_ua_private.h>
5#include <pjsip/sip_transport.h>
6#include <pjsip/sip_transaction.h>
7#include <pjsip/sip_types.h>
8#include <pjsip/sip_endpoint.h>
9#include <pjsip/sip_uri.h>
10#include <pjsip/sip_misc.h>
11#include <pjsip/sip_module.h>
12#include <pjsip/sip_event.h>
13#include <pjsip/sip_parser.h>
14#include <pj/string.h>
15#include <pj/log.h>
16#include <pj/os.h>
17#include <pj/guid.h>
18#include <pj/except.h>
19#include <pj/pool.h>
20
21/* TLS to keep dialog lock record (initialized by UA) */
22int pjsip_dlg_lock_tls_id;
23
24struct dialog_lock_data
25{
26 struct dialog_lock_data *prev;
27 pjsip_dlg *dlg;
28 int is_alive;
29};
30
31/*
32 * Static function prototypes.
33 */
34static void dlg_create_request_throw( pjsip_tx_data **p_tdata,
35 pjsip_dlg *dlg,
36 const pjsip_method *method,
37 int cseq );
38static int dlg_on_all_state_pre( pjsip_dlg *dlg,
39 pjsip_transaction *tsx,
40 pjsip_event *event);
41static int dlg_on_all_state_post( pjsip_dlg *dlg,
42 pjsip_transaction *tsx,
43 pjsip_event *event);
44static int dlg_on_state_null( pjsip_dlg *dlg,
45 pjsip_transaction *tsx,
46 pjsip_event *event);
47static int dlg_on_state_incoming( pjsip_dlg *dlg,
48 pjsip_transaction *tsx,
49 pjsip_event *event);
50static int dlg_on_state_calling( pjsip_dlg *dlg,
51 pjsip_transaction *tsx,
52 pjsip_event *event);
53static int dlg_on_state_proceeding( pjsip_dlg *dlg,
54 pjsip_transaction *tsx,
55 pjsip_event *event);
56static int dlg_on_state_proceeding_caller( pjsip_dlg *dlg,
57 pjsip_transaction *tsx,
58 pjsip_event *event);
59static int dlg_on_state_proceeding_callee( pjsip_dlg *dlg,
60 pjsip_transaction *tsx,
61 pjsip_event *event);
62static int dlg_on_state_connecting( pjsip_dlg *dlg,
63 pjsip_transaction *tsx,
64 pjsip_event *event);
65static int dlg_on_state_established( pjsip_dlg *dlg,
66 pjsip_transaction *tsx,
67 pjsip_event *event);
68static int dlg_on_state_disconnected( pjsip_dlg *dlg,
69 pjsip_transaction *tsx,
70 pjsip_event *event);
71static int dlg_on_state_terminated( pjsip_dlg *dlg,
72 pjsip_transaction *tsx,
73 pjsip_event *event);
74
75/*
76 * Dialog state handlers.
77 */
78static int (*dlg_state_handlers[])(struct pjsip_dlg *, pjsip_transaction *,
79 pjsip_event *) =
80{
81 &dlg_on_state_null,
82 &dlg_on_state_incoming,
83 &dlg_on_state_calling,
84 &dlg_on_state_proceeding,
85 &dlg_on_state_connecting,
86 &dlg_on_state_established,
87 &dlg_on_state_disconnected,
88 &dlg_on_state_terminated,
89};
90
91/*
92 * Dialog state names.
93 */
94static const char* dlg_state_names[] =
95{
96 "STATE_NULL",
97 "STATE_INCOMING",
98 "STATE_CALLING",
99 "STATE_PROCEEDING",
100 "STATE_CONNECTING",
101 "STATE_ESTABLISHED",
102 "STATE_DISCONNECTED",
103 "STATE_TERMINATED",
104};
105
106
107/*
108 * Get the dialog string state, normally for logging purpose.
109 */
110const char *pjsip_dlg_state_str(pjsip_dlg_state_e state)
111{
112 return dlg_state_names[state];
113}
114
115/* Lock dialog mutex. */
116static void lock_dialog(pjsip_dlg *dlg, struct dialog_lock_data *lck)
117{
118 struct dialog_lock_data *prev;
119
120 pj_mutex_lock(dlg->mutex);
121 prev = pj_thread_local_get(pjsip_dlg_lock_tls_id);
122 lck->prev = prev;
123 lck->dlg = dlg;
124 lck->is_alive = 1;
125 pj_thread_local_set(pjsip_dlg_lock_tls_id, lck);
126}
127
128/* Carefully unlock dialog mutex, protect against situation when the dialog
129 * has already been destroyed.
130 */
131static pj_status_t unlock_dialog(pjsip_dlg *dlg, struct dialog_lock_data *lck)
132{
133 pj_assert(pj_thread_local_get(pjsip_dlg_lock_tls_id) == lck);
134 pj_assert(dlg == lck->dlg);
135
136 pj_thread_local_set(pjsip_dlg_lock_tls_id, lck->prev);
137 if (lck->is_alive)
138 pj_mutex_unlock(dlg->mutex);
139
140 return lck->is_alive ? 0 : -1;
141}
142
143/*
144 * This is called by dialog's FSM to change dialog's state.
145 */
146static void dlg_set_state( pjsip_dlg *dlg, pjsip_dlg_state_e state,
147 pjsip_event *event)
148{
149 PJ_UNUSED_ARG(event);
150
151 PJ_LOG(4, (dlg->obj_name, "State %s-->%s (ev=%s, src=%s, data=%p)",
152 pjsip_dlg_state_str(dlg->state), pjsip_dlg_state_str(state),
153 event ? pjsip_event_str(event->type) : "",
154 event ? pjsip_event_str(event->src_type) : "",
155 event ? event->src.data : NULL));
156
157 dlg->state = state;
158 dlg->handle_tsx_event = dlg_state_handlers[state];
159}
160
161/*
162 * Invoke dialog's callback.
163 * This function is called by dialog's FSM, and interpret the event and call
164 * the corresponding callback registered by application.
165 */
166static void dlg_call_dlg_callback( pjsip_dlg *dlg, pjsip_dlg_event_e dlg_event,
167 pjsip_event *event )
168{
169 pjsip_dlg_callback *cb = dlg->ua->dlg_cb;
170 if (!cb) {
171 PJ_LOG(4,(dlg->obj_name, "Can not call callback (none registered)."));
172 return;
173 }
174
175 /* Low level event: call the all-events callback. */
176 if (cb->on_all_events) {
177 (*cb->on_all_events)(dlg, dlg_event, event);
178 }
179
180 /* Low level event: call the tx/rx callback if this is a tx/rx event. */
181 if (event->type == PJSIP_EVENT_BEFORE_TX && cb->on_before_tx)
182 {
183 (*cb->on_before_tx)(dlg, event->obj.tsx, event->src.tdata, event->data.long_data);
184 }
185 else if (event->type == PJSIP_EVENT_TX_MSG &&
186 event->src_type == PJSIP_EVENT_TX_MSG && cb->on_tx_msg)
187 {
188 (*cb->on_tx_msg)(dlg, event->obj.tsx, event->src.tdata);
189 }
190 else if (event->type == PJSIP_EVENT_RX_MSG &&
191 event->src_type == PJSIP_EVENT_RX_MSG && cb->on_rx_msg) {
192 (*cb->on_rx_msg)(dlg, event->obj.tsx, event->src.rdata);
193 }
194
195 /* Now trigger high level events.
196 * High level event should only occurs when dialog's state has changed,
197 * except for on_provisional, which may be called multiple times whenever
198 * response message is sent
199 */
200 if (dlg->state == PJSIP_DIALOG_STATE_PROCEEDING &&
201 (event->type== PJSIP_EVENT_TSX_STATE_CHANGED) &&
202 event->obj.tsx == dlg->invite_tsx)
203 {
204 /* Sent/received provisional responses. */
205 if (cb->on_provisional)
206 (*cb->on_provisional)(dlg, event->obj.tsx, event);
207 }
208
209 if (dlg_event == PJSIP_DIALOG_EVENT_MID_CALL_REQUEST) {
210 if (cb->on_mid_call_events)
211 (*cb->on_mid_call_events)(dlg, event);
212 return;
213 }
214
215 if (dlg_event != PJSIP_DIALOG_EVENT_STATE_CHANGED)
216 return;
217
218 if (dlg->state == PJSIP_DIALOG_STATE_INCOMING) {
219
220 /* New incoming dialog. */
221 pj_assert (event->src_type == PJSIP_EVENT_RX_MSG);
222 (*cb->on_incoming)(dlg, event->obj.tsx, event->src.rdata);
223
224 } else if (dlg->state == PJSIP_DIALOG_STATE_CALLING) {
225
226 /* Dialog has just sent the first INVITE. */
227 if (cb->on_calling) {
228 (*cb->on_calling)(dlg, event->obj.tsx, event->src.tdata);
229 }
230
231 } else if (dlg->state == PJSIP_DIALOG_STATE_DISCONNECTED) {
232
233 if (cb->on_disconnected)
234 (*cb->on_disconnected)(dlg, event);
235
236 } else if (dlg->state == PJSIP_DIALOG_STATE_TERMINATED) {
237
238 if (cb->on_terminated)
239 (*cb->on_terminated)(dlg);
240
241 pjsip_ua_destroy_dialog(dlg);
242
243 } else if (dlg->state == PJSIP_DIALOG_STATE_CONNECTING) {
244
245 if (cb->on_connecting)
246 (*cb->on_connecting)(dlg, event);
247
248 } else if (dlg->state == PJSIP_DIALOG_STATE_ESTABLISHED) {
249
250 if (cb->on_established)
251 (*cb->on_established)(dlg, event);
252 }
253}
254
255/*
256 * This callback receives event from the transaction layer (via User Agent),
257 * or from dialog timer (for 200/INVITE or ACK retransmission).
258 */
259void pjsip_dlg_on_tsx_event( pjsip_dlg *dlg,
260 pjsip_transaction *tsx,
261 pjsip_event *event)
262{
263 int status = 0;
264 struct dialog_lock_data lck;
265
266 PJ_LOG(4, (dlg->obj_name, "state=%s (evt=%s, src=%s)",
267 pjsip_dlg_state_str(dlg->state),
268 pjsip_event_str(event->type),
269 pjsip_event_str(event->src_type)));
270
271
272 lock_dialog(dlg, &lck);
273
274 status = dlg_on_all_state_pre( dlg, tsx, event);
275
276 if (status==0) {
277 status = (*dlg->handle_tsx_event)(dlg, tsx, event);
278 }
279 if (status==0) {
280 status = dlg_on_all_state_post( dlg, tsx, event);
281 }
282
283 unlock_dialog(dlg, &lck);
284}
285
286/*
287 * This function contains common processing in all states, and it is called
288 * before the FSM is invoked.
289 */
290static int dlg_on_all_state_pre( pjsip_dlg *dlg,
291 pjsip_transaction *tsx,
292 pjsip_event *event)
293{
294 PJ_UNUSED_ARG(event)
295
296 if (event->type != PJSIP_EVENT_TSX_STATE_CHANGED)
297 return 0;
298
299 if (tsx && (tsx->state==PJSIP_TSX_STATE_CALLING ||
300 tsx->state==PJSIP_TSX_STATE_TRYING))
301 {
302 ++dlg->pending_tsx_count;
303
304 } else if (tsx && tsx->state==PJSIP_TSX_STATE_DESTROYED)
305 {
306 --dlg->pending_tsx_count;
307 if (tsx == dlg->invite_tsx)
308 dlg->invite_tsx = NULL;
309 }
310
311 if (tsx->method.id == PJSIP_INVITE_METHOD) {
312 tsx->handle_ack = 1;
313 }
314 return 0;
315}
316
317
318/*
319 * This function contains common processing in all states, and it is called
320 * after the FSM is invoked.
321 */
322static int dlg_on_all_state_post( pjsip_dlg *dlg,
323 pjsip_transaction *tsx,
324 pjsip_event *event)
325{
326 PJ_UNUSED_ARG(event)
327
328 if (tsx && tsx->state==PJSIP_TSX_STATE_DESTROYED) {
329 if (dlg->pending_tsx_count == 0 &&
330 dlg->state != PJSIP_DIALOG_STATE_CONNECTING &&
331 dlg->state != PJSIP_DIALOG_STATE_ESTABLISHED &&
332 dlg->state != PJSIP_DIALOG_STATE_TERMINATED)
333 {
334 dlg_set_state(dlg, PJSIP_DIALOG_STATE_TERMINATED, event);
335 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
336 return -1;
337 }
338 }
339
340 return 0;
341}
342
343
344/*
345 * Internal function to initialize dialog, contains common initialization
346 * for both UAS and UAC dialog.
347 */
348static pj_status_t dlg_init( pjsip_dlg *dlg )
349{
350 /* Init mutex. */
351 dlg->mutex = pj_mutex_create(dlg->pool, "mdlg%p", 0);
352 if (!dlg->mutex) {
353 PJ_PERROR((dlg->obj_name, "pj_mutex_create()"));
354 return -1;
355 }
356
357 /* Init route-set (Initially empty) */
358 pj_list_init(&dlg->route_set);
359
360 /* Init auth credential list. */
361 pj_list_init(&dlg->auth_sess);
362
363 return PJ_SUCCESS;
364}
365
366/*
367 * This one is called just before dialog is destroyed.
368 * It is called while mutex is held.
369 */
370PJ_DEF(void) pjsip_on_dialog_destroyed( pjsip_dlg *dlg )
371{
372 struct dialog_lock_data *lck;
373
374 //PJ_TODO(CHECK_THIS);
375 pj_assert(dlg->pending_tsx_count == 0);
376
377 /* Mark dialog as dead. */
378 lck = pj_thread_local_get(pjsip_dlg_lock_tls_id);
379 while (lck) {
380 if (lck->dlg == dlg)
381 lck->is_alive = 0;
382 lck = lck->prev;
383 }
384}
385
386/*
387 * Initialize dialog from the received request.
388 * This is an internal function which is called by the User Agent (sip_ua.c),
389 * and it will initialize most of dialog's properties with values from the
390 * received message.
391 */
392pj_status_t pjsip_dlg_init_from_rdata( pjsip_dlg *dlg, pjsip_rx_data *rdata )
393{
394 pjsip_msg *msg = rdata->msg;
395 pjsip_to_hdr *to;
396 pjsip_contact_hdr *contact;
397 pjsip_name_addr *name_addr;
398 pjsip_url *url;
399 unsigned flag;
400 pjsip_event event;
401
402 pj_assert(dlg && rdata);
403
404 PJ_LOG(5, (dlg->obj_name, "init_from_rdata(%p)", rdata));
405
406 /* Must be an INVITE request. */
407 pj_assert(msg->type == PJSIP_REQUEST_MSG &&
408 msg->line.req.method.id == PJSIP_INVITE_METHOD);
409
410 /* Init general dialog data. */
411 if (dlg_init(dlg) != PJ_SUCCESS) {
412 return -1;
413 }
414
415 /* Get the To header. */
416 to = rdata->to;
417
418 /* Copy URI in the To header as our local URI. */
419 dlg->local.info = pjsip_hdr_clone( dlg->pool, to);
420
421 /* Set tag in the local info. */
422 dlg->local.info->tag = dlg->local.tag;
423
424 /* Create local Contact to be advertised in the response.
425 * At the moment, just copy URI from the local URI as our contact.
426 */
427 dlg->local.contact = pjsip_contact_hdr_create( dlg->pool );
428 dlg->local.contact->star = 0;
429 name_addr = (pjsip_name_addr *)dlg->local.info->uri;
430 dlg->local.contact->uri = (pjsip_uri*) name_addr;
431 url = (pjsip_url*) name_addr->uri;
432 //url->port = rdata->via->sent_by.port;
433 //url->port = pj_sockaddr_get_port( pjsip_transport_get_local_addr(rdata->transport) );
434
435 /* Save remote URI. */
436 dlg->remote.info = pjsip_hdr_clone( dlg->pool, rdata->from );
437 pjsip_fromto_set_to( dlg->remote.info );
438 pj_strdup( dlg->pool, &dlg->remote.tag, &rdata->from->tag );
439
440 /* Save remote Contact. */
441 contact = pjsip_msg_find_hdr( msg, PJSIP_H_CONTACT, NULL);
442 if (contact) {
443 dlg->remote.contact = pjsip_hdr_clone( dlg->pool, contact );
444 } else {
445 PJ_LOG(3,(dlg->obj_name, "No Contact header in INVITE from %s",
446 pj_sockaddr_get_str_addr(&rdata->addr)));
447 dlg->remote.contact = pjsip_contact_hdr_create( dlg->pool );
448 dlg->remote.contact->uri = dlg->remote.info->uri;
449 }
450
451 /* Save Call-ID. */
452 dlg->call_id = pjsip_cid_hdr_create(dlg->pool);
453 pj_strdup( dlg->pool, &dlg->call_id->id, &rdata->call_id );
454
455 /* Initialize local CSeq and save remote CSeq.*/
456 dlg->local.cseq = rdata->timestamp.sec & 0xFFFF;
457 dlg->remote.cseq = rdata->cseq->cseq;
458
459 /* Secure? */
460 flag = pjsip_transport_get_flag(rdata->transport);
461 dlg->secure = (flag & PJSIP_TRANSPORT_SECURE) != 0;
462
463 /* Initial state is NULL. */
464 event.type = event.src_type = PJSIP_EVENT_RX_MSG;
465 event.src.rdata = rdata;
466 dlg_set_state(dlg, PJSIP_DIALOG_STATE_NULL, &event);
467
468 PJ_LOG(5, (dlg->obj_name, "init_from_rdata(%p) complete", rdata));
469 return PJ_SUCCESS;
470}
471
472/*
473 * Set the contact details.
474 */
475PJ_DEF(pj_status_t) pjsip_dlg_set_contact( pjsip_dlg *dlg,
476 const pj_str_t *contact )
477{
478 pjsip_uri *local_uri;
479 pj_str_t tmp;
480
481 pj_strdup_with_null(dlg->pool, &tmp, contact);
482 local_uri = pjsip_parse_uri( dlg->pool, tmp.ptr, tmp.slen,
483 PJSIP_PARSE_URI_AS_NAMEADDR);
484 if (local_uri == NULL) {
485 PJ_LOG(2, (dlg->obj_name, "set_contact: invalid URI"));
486 return -1;
487 }
488
489 dlg->local.contact->star = 0;
490 dlg->local.contact->uri = local_uri;
491 return 0;
492}
493
494/*
495 * Set route set.
496 */
497PJ_DEF(pj_status_t) pjsip_dlg_set_route_set( pjsip_dlg *dlg,
498 const pjsip_route_hdr *route_set )
499{
500 pjsip_route_hdr *hdr;
501
502 pj_list_init(&dlg->route_set);
503 hdr = route_set->next;
504 while (hdr != route_set) {
505 pjsip_route_hdr *cloned = pjsip_hdr_clone(dlg->pool, hdr);
506 pj_list_insert_before( &dlg->route_set, cloned);
507 hdr = hdr->next;
508 }
509 return 0;
510}
511
512/*
513 * Set route set without cloning the header.
514 */
515PJ_DEF(pj_status_t) pjsip_dlg_set_route_set_np( pjsip_dlg *dlg,
516 pjsip_route_hdr *route_set)
517{
518 pjsip_route_hdr *hdr;
519
520 pj_list_init(&dlg->route_set);
521 hdr = route_set->next;
522 while (hdr != route_set) {
523 pj_list_insert_before( &dlg->route_set, hdr);
524 hdr = hdr->next;
525 }
526 return 0;
527}
528
529/*
530 * Application calls this function when it wants to initiate an outgoing
531 * dialog (incoming dialogs are created automatically by UA when it receives
532 * INVITE, by calling pjsip_dlg_init_from_rdata()).
533 * This function should initialize most of the dialog's properties.
534 */
535PJ_DEF(pj_status_t) pjsip_dlg_init( pjsip_dlg *dlg,
536 const pj_str_t *c_local_info,
537 const pj_str_t *c_remote_info,
538 const pj_str_t *c_target)
539{
540 pj_time_val tv;
541 pjsip_event event;
542 pj_str_t buf;
543
544 if (!dlg || !c_local_info || !c_remote_info) {
545 pj_assert(dlg && c_local_info && c_remote_info);
546 return -1;
547 }
548
549 PJ_LOG(5, (dlg->obj_name, "initializing"));
550
551 /* Init general dialog */
552 if (dlg_init(dlg) != PJ_SUCCESS) {
553 return -1;
554 }
555
556 /* Duplicate local info. */
557 pj_strdup_with_null( dlg->pool, &buf, c_local_info);
558
559 /* Build local URI. */
560 dlg->local.target = pjsip_parse_uri(dlg->pool, buf.ptr, buf.slen,
561 PJSIP_PARSE_URI_AS_NAMEADDR);
562 if (dlg->local.target == NULL) {
563 PJ_LOG(2, (dlg->obj_name,
564 "pjsip_dlg_init: invalid local URI %s", buf.ptr));
565 return -1;
566 }
567
568 /* Set local URI. */
569 dlg->local.info = pjsip_from_hdr_create(dlg->pool);
570 dlg->local.info->uri = dlg->local.target;
571 dlg->local.info->tag = dlg->local.tag;
572
573 /* Create local Contact to be advertised in the response. */
574 dlg->local.contact = pjsip_contact_hdr_create( dlg->pool );
575 dlg->local.contact->star = 0;
576 dlg->local.contact->uri = dlg->local.target;
577
578 /* Set remote URI. */
579 dlg->remote.info = pjsip_to_hdr_create(dlg->pool);
580
581 /* Duplicate to buffer. */
582 pj_strdup_with_null( dlg->pool, &buf, c_remote_info);
583
584 /* Build remote info. */
585 dlg->remote.info->uri = pjsip_parse_uri( dlg->pool, buf.ptr, buf.slen,
586 PJSIP_PARSE_URI_AS_NAMEADDR);
587 if (dlg->remote.info->uri == NULL) {
588 PJ_LOG(2, (dlg->obj_name,
589 "pjsip_dlg_init: invalid remote URI %s", buf.ptr));
590 return -1;
591 }
592
593 /* Set remote Contact initially equal to the remote URI. */
594 dlg->remote.contact = pjsip_contact_hdr_create(dlg->pool);
595 dlg->remote.contact->star = 0;
596 dlg->remote.contact->uri = dlg->remote.info->uri;
597
598 /* Set initial remote target. */
599 if (c_target != NULL) {
600 pj_strdup_with_null( dlg->pool, &buf, c_target);
601 dlg->remote.target = pjsip_parse_uri( dlg->pool, buf.ptr, buf.slen, 0);
602 if (dlg->remote.target == NULL) {
603 PJ_LOG(2, (dlg->obj_name,
604 "pjsip_dlg_init: invalid remote target %s", buf.ptr));
605 return -1;
606 }
607 } else {
608 dlg->remote.target = dlg->remote.info->uri;
609 }
610
611 /* Create globally unique Call-ID */
612 dlg->call_id = pjsip_cid_hdr_create(dlg->pool);
613 pj_create_unique_string( dlg->pool, &dlg->call_id->id );
614
615 /* Local and remote CSeq */
616 pj_gettimeofday(&tv);
617 dlg->local.cseq = tv.sec & 0xFFFF;
618 dlg->remote.cseq = 0;
619
620 /* Initial state is NULL. */
621 event.type = event.src_type = PJSIP_EVENT_TX_MSG;
622 event.src.data = NULL;
623 dlg_set_state(dlg, PJSIP_DIALOG_STATE_NULL, &event);
624
625 /* Done. */
626 PJ_LOG(4, (dlg->obj_name, "%s dialog initialized, From: %.*s, To: %.*s",
627 pjsip_role_name(dlg->role),
628 c_local_info->slen, c_local_info->ptr,
629 c_remote_info->slen, c_remote_info->ptr));
630
631 return PJ_SUCCESS;
632}
633
634/*
635 * Set credentials.
636 */
637PJ_DEF(pj_status_t) pjsip_dlg_set_credentials( pjsip_dlg *dlg,
638 int count,
639 const pjsip_cred_info *cred)
640{
641 if (count > 0) {
642 dlg->cred_info = pj_pool_alloc(dlg->pool, count * sizeof(pjsip_cred_info));
643 pj_memcpy(dlg->cred_info, cred, count * sizeof(pjsip_cred_info));
644 }
645 dlg->cred_count = count;
646 return 0;
647}
648
649/*
650 * Create a new request within dialog (i.e. after the dialog session has been
651 * established). The construction of such requests follows the rule in
652 * RFC3261 section 12.2.1.
653 */
654static void dlg_create_request_throw( pjsip_tx_data **p_tdata,
655 pjsip_dlg *dlg,
656 const pjsip_method *method,
657 int cseq )
658{
659 pjsip_tx_data *tdata;
660 pjsip_contact_hdr *contact;
661 pjsip_route_hdr *route, *end_list;
662
663 /* Contact Header field.
664 * Contact can only be present in requests that establish dialog (in the
665 * core SIP spec, only INVITE).
666 */
667 if (method->id == PJSIP_INVITE_METHOD)
668 contact = dlg->local.contact;
669 else
670 contact = NULL;
671
672 tdata = pjsip_endpt_create_request_from_hdr( dlg->ua->endpt,
673 method,
674 dlg->remote.target,
675 dlg->local.info,
676 dlg->remote.info,
677 contact,
678 dlg->call_id,
679 cseq,
680 NULL);
681 if (!tdata) {
682 PJ_THROW(1);
683 return;
684 }
685
686 /* Just copy dialog route-set to Route header.
687 * The transaction will do the processing as specified in Section 12.2.1
688 * of RFC 3261 in function tsx_process_route() in sip_transaction.c.
689 */
690 route = dlg->route_set.next;
691 end_list = &dlg->route_set;
692 for (; route != end_list; route = route->next ) {
693 pjsip_route_hdr *r;
694 r = pjsip_hdr_shallow_clone( tdata->pool, route );
695 pjsip_routing_hdr_set_route(r);
696 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)r);
697 }
698
699 /* Copy authorization headers. */
700 pjsip_auth_init_req( dlg->pool, tdata, &dlg->auth_sess,
701 dlg->cred_count, dlg->cred_info);
702
703 *p_tdata = tdata;
704}
705
706
707/*
708 * This function is called by application to create new outgoing request
709 * message for this dialog. After the request is created, application can
710 * modify the message (such adding headers), and eventually send the request.
711 */
712PJ_DEF(pjsip_tx_data*) pjsip_dlg_create_request( pjsip_dlg *dlg,
713 const pjsip_method *method,
714 int cseq)
715{
716 PJ_USE_EXCEPTION;
717 struct dialog_lock_data lck;
718 pjsip_tx_data *tdata = NULL;
719
720 pj_assert(dlg != NULL && method != NULL);
721 if (!dlg || !method) {
722 return NULL;
723 }
724
725 PJ_LOG(5, (dlg->obj_name, "Creating request"));
726
727 /* Lock dialog. */
728 lock_dialog(dlg, &lck);
729
730 /* Use outgoing CSeq and increment it by one. */
731 if (cseq < 0)
732 cseq = dlg->local.cseq + 1;
733
734 PJ_LOG(5, (dlg->obj_name, "creating request %.*s cseq=%d",
735 method->name.slen, method->name.ptr, cseq));
736
737 /* Create the request. */
738 PJ_TRY {
739 dlg_create_request_throw(&tdata, dlg, method, cseq);
740 PJ_LOG(5, (dlg->obj_name, "request data %s created", tdata->obj_name));
741 }
742 PJ_DEFAULT {
743 /* Failed! Delete transmit data. */
744 if (tdata) {
745 pjsip_tx_data_dec_ref( tdata );
746 tdata = NULL;
747 }
748 }
749 PJ_END;
750
751 /* Unlock dialog. */
752 unlock_dialog(dlg, &lck);
753
754 return tdata;
755}
756
757/*
758 * Sends request.
759 * Select the transport for the request message
760 */
761static pj_status_t dlg_send_request( pjsip_dlg *dlg, pjsip_tx_data *tdata )
762{
763 pjsip_transaction *tsx;
764 pj_status_t status = PJ_SUCCESS;
765 struct dialog_lock_data lck;
766
767 pj_assert(dlg != NULL && tdata != NULL);
768 if (!dlg || !tdata) {
769 return -1;
770 }
771
772 PJ_LOG(5, (dlg->obj_name, "sending request %s", tdata->obj_name));
773
774 /* Lock dialog. */
775 lock_dialog(dlg, &lck);
776
777 /* Create a new transaction. */
778 tsx = pjsip_endpt_create_tsx( dlg->ua->endpt );
779 if (!tsx) {
780 unlock_dialog(dlg, &lck);
781 return -1;
782 }
783
784 PJ_LOG(4, (dlg->obj_name, "Created new UAC transaction: %s", tsx->obj_name));
785
786 /* Initialize transaction */
787 tsx->module_data[dlg->ua->mod_id] = dlg;
788 status = pjsip_tsx_init_uac( tsx, tdata );
789 if (status != PJ_SUCCESS) {
790 unlock_dialog(dlg, &lck);
791 pjsip_endpt_destroy_tsx( dlg->ua->endpt, tsx );
792 return -1;
793 }
794 pjsip_endpt_register_tsx( dlg->ua->endpt, tsx );
795
796 /* Start the transaction. */
797 pjsip_tsx_on_tx_msg(tsx, tdata);
798
799 /* Unlock dialog. */
800 unlock_dialog(dlg, &lck);
801
802 return status;
803}
804
805/*
806 * This function can be called by application to send ANY outgoing message
807 * to remote party.
808 */
809PJ_DEF(pj_status_t) pjsip_dlg_send_msg( pjsip_dlg *dlg, pjsip_tx_data *tdata )
810{
811 pj_status_t status;
812 int tsx_status;
813 struct dialog_lock_data lck;
814
815 pj_assert(dlg != NULL && tdata != NULL);
816 if (!dlg || !tdata) {
817 return -1;
818 }
819
820 lock_dialog(dlg, &lck);
821
822 if (tdata->msg->type == PJSIP_REQUEST_MSG) {
823 int request_cseq;
824 pjsip_msg *msg = tdata->msg;
825 pjsip_cseq_hdr *cseq_hdr;
826
827 switch (msg->line.req.method.id) {
828 case PJSIP_CANCEL_METHOD:
829
830 /* Check the INVITE transaction state. */
831 tsx_status = dlg->invite_tsx->status_code;
832 if (tsx_status >= 200) {
833 /* Already terminated. Can't cancel. */
834 status = -1;
835 goto on_return;
836 }
837
838 /* If we've got provisional response, then send CANCEL and wait for
839 * the response to INVITE to arrive. Otherwise just send CANCEL and
840 * terminate the INVITE.
841 */
842 if (tsx_status < 100) {
843 pjsip_tsx_terminate( dlg->invite_tsx,
844 PJSIP_SC_REQUEST_TERMINATED);
845 status = 0;
846 goto on_return;
847 }
848
849 status = 0;
850 request_cseq = dlg->invite_tsx->cseq;
851 break;
852
853 case PJSIP_ACK_METHOD:
854 /* Sending ACK outside of transaction is not supported at present! */
855 pj_assert(0);
856 status = 0;
857 request_cseq = dlg->local.cseq;
858 break;
859
860 case PJSIP_INVITE_METHOD:
861 /* For an initial INVITE, reset dialog state to NULL so we get
862 * 'normal' UAC notifications such as on_provisional(), etc.
863 * Initial INVITE is the request that is sent when the dialog has
864 * not been established yet. It's not necessarily the first INVITE
865 * sent, as when the Authorization fails, subsequent INVITE are also
866 * considered as an initial INVITE.
867 */
868 if (dlg->state != PJSIP_DIALOG_STATE_ESTABLISHED) {
869 /* Set state to NULL. */
870 dlg_set_state(dlg, PJSIP_DIALOG_STATE_NULL, NULL);
871
872 } else {
873 /* This is a re-INVITE */
874 }
875 status = 0;
876 request_cseq = dlg->local.cseq + 1;
877 break;
878
879 default:
880 status = 0;
881 request_cseq = dlg->local.cseq + 1;
882 break;
883 }
884
885 if (status != 0)
886 goto on_return;
887
888 /* Update dialog's local CSeq, if necessary. */
889 if (request_cseq != dlg->local.cseq)
890 dlg->local.cseq = request_cseq;
891
892 /* Update CSeq header in the request. */
893 cseq_hdr = (pjsip_cseq_hdr*) pjsip_msg_find_hdr( tdata->msg,
894 PJSIP_H_CSEQ, NULL);
895 pj_assert(cseq_hdr != NULL);
896
897 /* Update the CSeq */
898 cseq_hdr->cseq = request_cseq;
899
900 /* Force the whole message to be re-printed. */
901 pjsip_tx_data_invalidate_msg( tdata );
902
903 /* Now send the request. */
904 status = dlg_send_request(dlg, tdata);
905
906 } else {
907 /*
908 * This is only valid for sending response to INVITE!
909 */
910 pjsip_cseq_hdr *cseq_hdr;
911
912 if (dlg->invite_tsx == NULL || dlg->invite_tsx->status_code >= 200) {
913 status = -1;
914 goto on_return;
915 }
916
917 cseq_hdr = (pjsip_cseq_hdr*) pjsip_msg_find_hdr( tdata->msg,
918 PJSIP_H_CSEQ, NULL);
919 pj_assert(cseq_hdr);
920
921 if (cseq_hdr->method.id != PJSIP_INVITE_METHOD) {
922 status = -1;
923 goto on_return;
924 }
925
926 pj_assert(cseq_hdr->cseq == dlg->invite_tsx->cseq);
927
928 pjsip_tsx_on_tx_msg(dlg->invite_tsx, tdata);
929 status = 0;
930 }
931
932on_return:
933 /* Unlock dialog. */
934 unlock_dialog(dlg, &lck);
935
936 /* Whatever happen delete the message. */
937 pjsip_tx_data_dec_ref( tdata );
938
939 return status;
940}
941
942/*
943 * Sends outgoing invitation.
944 */
945PJ_DEF(pjsip_tx_data*) pjsip_dlg_invite( pjsip_dlg *dlg )
946{
947 pjsip_method method;
948 struct dialog_lock_data lck;
949 const pjsip_allow_hdr *allow_hdr;
950 pjsip_tx_data *tdata;
951
952 pj_assert(dlg != NULL);
953 if (!dlg) {
954 return NULL;
955 }
956
957 PJ_LOG(4, (dlg->obj_name, "request to send invitation"));
958
959 /* Lock dialog. */
960 lock_dialog(dlg, &lck);
961
962 /* Create request. */
963 pjsip_method_set( &method, PJSIP_INVITE_METHOD);
964 tdata = pjsip_dlg_create_request( dlg, &method, -1 );
965 if (tdata == NULL) {
966 unlock_dialog(dlg, &lck);
967 return NULL;
968 }
969
970 /* Invite SHOULD contain "Allow" header. */
971 allow_hdr = pjsip_endpt_get_allow_hdr( dlg->ua->endpt );
972 if (allow_hdr) {
973 pjsip_msg_add_hdr( tdata->msg,
974 pjsip_hdr_shallow_clone( tdata->pool, allow_hdr));
975 }
976
977 /* Unlock dialog. */
978 unlock_dialog(dlg, &lck);
979
980 return tdata;
981}
982
983/*
984 * Cancel pending outgoing dialog invitation.
985 */
986PJ_DEF(pjsip_tx_data*) pjsip_dlg_cancel( pjsip_dlg *dlg )
987{
988 pjsip_tx_data *tdata = NULL;
989 struct dialog_lock_data lck;
990
991 pj_assert(dlg != NULL);
992 if (!dlg) {
993 return NULL;
994 }
995
996 PJ_LOG(4, (dlg->obj_name, "request to cancel invitation"));
997
998 lock_dialog(dlg, &lck);
999
1000 /* Check the INVITE transaction. */
1001 if (dlg->invite_tsx == NULL || dlg->role != PJSIP_ROLE_UAC) {
1002 PJ_LOG(2, (dlg->obj_name, "pjsip_dlg_cancel failed: "
1003 "no INVITE transaction found"));
1004 goto on_return;
1005 }
1006
1007 /* Construct the CANCEL request. */
1008 tdata = pjsip_endpt_create_cancel( dlg->ua->endpt,
1009 dlg->invite_tsx->last_tx );
1010 if (tdata == NULL) {
1011 PJ_LOG(2, (dlg->obj_name, "pjsip_dlg_cancel failed: "
1012 "unable to construct request"));
1013 goto on_return;
1014 }
1015
1016 /* Add reference counter to tdata. */
1017 pjsip_tx_data_add_ref(tdata);
1018
1019on_return:
1020 unlock_dialog(dlg, &lck);
1021 return tdata;
1022}
1023
1024
1025/*
1026 * Answer incoming dialog invitation, with either provisional responses
1027 * or a final response.
1028 */
1029PJ_DEF(pjsip_tx_data*) pjsip_dlg_answer( pjsip_dlg *dlg, int code )
1030{
1031 pjsip_tx_data *tdata = NULL;
1032 pjsip_msg *msg;
1033 struct dialog_lock_data lck;
1034
1035 pj_assert(dlg != NULL);
1036 if (!dlg) {
1037 return NULL;
1038 }
1039
1040 PJ_LOG(4, (dlg->obj_name, "pjsip_dlg_answer: code=%d", code));
1041
1042 /* Lock dialog. */
1043 lock_dialog(dlg, &lck);
1044
1045 /* Must have pending INVITE. */
1046 if (dlg->invite_tsx == NULL) {
1047 PJ_LOG(2, (dlg->obj_name, "pjsip_dlg_answer: no INVITE transaction found"));
1048 goto on_return;
1049 }
1050 /* Must be UAS. */
1051 if (dlg->role != PJSIP_ROLE_UAS) {
1052 PJ_LOG(2, (dlg->obj_name, "pjsip_dlg_answer: not UAS"));
1053 goto on_return;
1054 }
1055 /* Must have not answered with final response before. */
1056 if (dlg->invite_tsx->status_code >= 200) {
1057 PJ_LOG(2, (dlg->obj_name, "pjsip_dlg_answer: transaction already terminated "
1058 "with status %d", dlg->invite_tsx->status_code));
1059 goto on_return;
1060 }
1061
1062 /* Get transmit data and the message.
1063 * We will rewrite the message with a new status code.
1064 */
1065 tdata = dlg->invite_tsx->last_tx;
1066 msg = tdata->msg;
1067
1068 /* Set status code and reason phrase. */
1069 if (code < 100 || code >= 700) code = 500;
1070 msg->line.status.code = code;
1071 msg->line.status.reason = *pjsip_get_status_text(code);
1072
1073 /* For 2xx response, Contact and Record-Route must be added. */
1074 if (PJSIP_IS_STATUS_IN_CLASS(code,200)) {
1075 const pjsip_allow_hdr *allow_hdr;
1076
1077 if (pjsip_msg_find_hdr(msg, PJSIP_H_CONTACT, NULL) == NULL) {
1078 pjsip_contact_hdr *contact;
1079 contact = pjsip_hdr_shallow_clone( tdata->pool, dlg->local.contact);
1080 pjsip_msg_add_hdr( msg, (pjsip_hdr*)contact );
1081 }
1082
1083 /* 2xx response MUST contain "Allow" header. */
1084 allow_hdr = pjsip_endpt_get_allow_hdr( dlg->ua->endpt );
1085 if (allow_hdr) {
1086 pjsip_msg_add_hdr( msg, pjsip_hdr_shallow_clone( tdata->pool, allow_hdr));
1087 }
1088 }
1089
1090 /* for all but 100 responses, To-tag must be set. */
1091 if (code != 100) {
1092 pjsip_to_hdr *to;
1093 to = pjsip_msg_find_hdr( msg, PJSIP_H_TO, NULL);
1094 to->tag = dlg->local.tag;
1095 }
1096
1097 /* Reset packet buffer. */
1098 pjsip_tx_data_invalidate_msg(tdata);
1099
1100 /* Add reference counter */
1101 pjsip_tx_data_add_ref(tdata);
1102
1103on_return:
1104
1105 /* Unlock dialog. */
1106 unlock_dialog(dlg, &lck);
1107
1108 return tdata;
1109}
1110
1111
1112/*
1113 * Send BYE request to terminate the dialog's session.
1114 */
1115PJ_DEF(pjsip_tx_data*) pjsip_dlg_bye( pjsip_dlg *dlg )
1116{
1117 pjsip_method method;
1118 struct dialog_lock_data lck;
1119 pjsip_tx_data *tdata;
1120
1121 if (!dlg) {
1122 pj_assert(dlg != NULL);
1123 return NULL;
1124 }
1125
1126 PJ_LOG(4, (dlg->obj_name, "request to terminate session"));
1127
1128 lock_dialog(dlg, &lck);
1129
1130 pjsip_method_set( &method, PJSIP_BYE_METHOD);
1131 tdata = pjsip_dlg_create_request( dlg, &method, -1 );
1132
1133 unlock_dialog(dlg, &lck);
1134
1135 return tdata;
1136}
1137
1138/*
1139 * High level function to disconnect dialog's session. Depending on dialog's
1140 * state, this function will either send CANCEL, final response, or BYE to
1141 * trigger the disconnection. A status code must be supplied, which will be
1142 * sent if dialog will be transmitting a final response to INVITE.
1143 */
1144PJ_DEF(pjsip_tx_data*) pjsip_dlg_disconnect( pjsip_dlg *dlg,
1145 int status_code )
1146{
1147 pjsip_tx_data *tdata = NULL;
1148
1149 pj_assert(dlg != NULL);
1150 if (!dlg) {
1151 return NULL;
1152 }
1153
1154 switch (dlg->state) {
1155 case PJSIP_DIALOG_STATE_INCOMING:
1156 tdata = pjsip_dlg_answer(dlg, status_code);
1157 break;
1158
1159 case PJSIP_DIALOG_STATE_CALLING:
1160 tdata = pjsip_dlg_cancel(dlg);
1161 break;
1162
1163 case PJSIP_DIALOG_STATE_PROCEEDING:
1164 if (dlg->role == PJSIP_ROLE_UAC) {
1165 tdata = pjsip_dlg_cancel(dlg);
1166 } else {
1167 tdata = pjsip_dlg_answer(dlg, status_code);
1168 }
1169 break;
1170
1171 case PJSIP_DIALOG_STATE_ESTABLISHED:
1172 tdata = pjsip_dlg_bye(dlg);
1173 break;
1174
1175 default:
1176 PJ_LOG(4,(dlg->obj_name, "Invalid state %s in pjsip_dlg_disconnect()",
1177 dlg_state_names[dlg->state]));
1178 break;
1179 }
1180
1181 return tdata;
1182}
1183
1184/*
1185 * Handling of the receipt of 2xx/INVITE response.
1186 */
1187static void dlg_on_recv_2xx_invite( pjsip_dlg *dlg,
1188 pjsip_event *event )
1189{
1190 pjsip_msg *msg;
1191 pjsip_contact_hdr *contact;
1192 pjsip_hdr *hdr, *end_hdr;
1193 pjsip_method method;
1194 pjsip_tx_data *ack_tdata;
1195
1196 /* Get the message */
1197 msg = event->src.rdata->msg;
1198
1199 /* Update remote's tag information. */
1200 pj_strdup(dlg->pool, &dlg->remote.info->tag, &event->src.rdata->to_tag);
1201
1202 /* Copy Contact information in the 2xx/INVITE response to dialog's.
1203 * remote contact
1204 */
1205 contact = pjsip_msg_find_hdr( msg, PJSIP_H_CONTACT, NULL);
1206 if (contact) {
1207 dlg->remote.contact = pjsip_hdr_clone( dlg->pool, contact );
1208 } else {
1209 /* duplicate contact from "From" header (?) */
1210 PJ_LOG(4,(dlg->obj_name, "Received 200/OK to INVITE with no Contact!"));
1211 dlg->remote.contact = pjsip_contact_hdr_create(dlg->pool);
1212 dlg->remote.contact->uri = dlg->remote.info->uri;
1213 }
1214
1215 /* Copy Record-Route header (in reverse order) as dialog's route-set,
1216 * overwriting previous route-set, if any, even if the received route-set
1217 * is empty.
1218 */
1219 pj_list_init(&dlg->route_set);
1220 end_hdr = &msg->hdr;
1221 for (hdr = msg->hdr.prev; hdr!=end_hdr; hdr = hdr->prev) {
1222 if (hdr->type == PJSIP_H_RECORD_ROUTE) {
1223 pjsip_route_hdr *r;
1224 r = pjsip_hdr_clone(dlg->pool, hdr);
1225 pjsip_routing_hdr_set_route(r);
1226 pj_list_insert_before(&dlg->route_set, r);
1227 }
1228 }
1229
1230 /* On receipt of 200/INVITE response, send ACK.
1231 * This ack must be saved and retransmitted whenever we receive
1232 * 200/INVITE retransmission, until 64*T1 seconds elapsed.
1233 */
1234 pjsip_method_set( &method, PJSIP_ACK_METHOD);
1235 ack_tdata = pjsip_dlg_create_request( dlg, &method, dlg->invite_tsx->cseq);
1236 if (ack_tdata == NULL) {
1237 //PJ_TODO(HANDLE_CREATE_ACK_FAILURE)
1238 PJ_LOG(2, (dlg->obj_name, "Error sending ACK msg: can't create request"));
1239 return;
1240 }
1241
1242 /* Send with the transaction. */
1243 pjsip_tsx_on_tx_ack( dlg->invite_tsx, ack_tdata);
1244
1245 /* Decrement reference counter because pjsip_dlg_create_request
1246 * automatically increments the request.
1247 */
1248 pjsip_tx_data_dec_ref( ack_tdata );
1249}
1250
1251/*
1252 * State NULL, before any events have been received.
1253 */
1254static int dlg_on_state_null( pjsip_dlg *dlg,
1255 pjsip_transaction *tsx,
1256 pjsip_event *event)
1257{
1258 if (event->type == PJSIP_EVENT_TSX_STATE_CHANGED &&
1259 event->src_type == PJSIP_EVENT_RX_MSG)
1260 {
1261 pjsip_hdr *hdr, *hdr_list;
1262
1263 pj_assert(tsx->method.id == PJSIP_INVITE_METHOD);
1264
1265 /* Save the INVITE transaction. */
1266 dlg->invite_tsx = tsx;
1267
1268 /* Change state to INCOMING */
1269 dlg_set_state(dlg, PJSIP_DIALOG_STATE_INCOMING, event);
1270
1271 /* Create response buffer. */
1272 tsx->last_tx = pjsip_endpt_create_response( dlg->ua->endpt, event->src.rdata, 100);
1273 pjsip_tx_data_add_ref(tsx->last_tx);
1274
1275 /* Copy the Record-Route headers into dialog's route_set, maintaining
1276 * the order.
1277 */
1278 pj_list_init(&dlg->route_set);
1279 hdr_list = &event->src.rdata->msg->hdr;
1280 hdr = hdr_list->next;
1281 while (hdr != hdr_list) {
1282 if (hdr->type == PJSIP_H_RECORD_ROUTE) {
1283 pjsip_route_hdr *route;
1284 route = pjsip_hdr_clone(dlg->pool, hdr);
1285 pjsip_routing_hdr_set_route(route);
1286 pj_list_insert_before(&dlg->route_set, route);
1287 }
1288 hdr = hdr->next;
1289 }
1290
1291 /* Notify application. */
1292 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1293
1294 } else if (event->type == PJSIP_EVENT_TSX_STATE_CHANGED &&
1295 event->src_type == PJSIP_EVENT_TX_MSG)
1296 {
1297 pj_assert(tsx->method.id == PJSIP_INVITE_METHOD);
1298
1299 /* Save the INVITE transaction. */
1300 dlg->invite_tsx = tsx;
1301
1302 /* Change state to CALLING. */
1303 dlg_set_state(dlg, PJSIP_DIALOG_STATE_CALLING, event);
1304
1305 /* Notify application. */
1306 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1307
1308 } else {
1309 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_OTHER, event);
1310 }
1311
1312 return 0;
1313}
1314
1315/*
1316 * State INCOMING is after the (callee) dialog has been initialized with
1317 * the incoming request, but before any responses is sent by the dialog.
1318 */
1319static int dlg_on_state_incoming( pjsip_dlg *dlg,
1320 pjsip_transaction *tsx,
1321 pjsip_event *event)
1322{
1323 return dlg_on_state_proceeding_callee( dlg, tsx, event );
1324}
1325
1326/*
1327 * State CALLING is after the (caller) dialog has sent outgoing invitation
1328 * but before any responses are received.
1329 */
1330static int dlg_on_state_calling( pjsip_dlg *dlg,
1331 pjsip_transaction *tsx,
1332 pjsip_event *event)
1333{
1334 if (tsx == dlg->invite_tsx) {
1335 return dlg_on_state_proceeding_caller( dlg, tsx, event );
1336 }
1337 return 0;
1338}
1339
1340/*
1341 * State PROCEEDING is after provisional response is received.
1342 * Since the processing is similar to state CALLING, this function is also
1343 * called for CALLING state.
1344 */
1345static int dlg_on_state_proceeding_caller( pjsip_dlg *dlg,
1346 pjsip_transaction *tsx,
1347 pjsip_event *event)
1348{
1349 int dlg_is_terminated = 0;
1350
1351 /* We only care about our INVITE transaction.
1352 * Ignore other transaction progression (such as CANCEL).
1353 */
1354 if (tsx != dlg->invite_tsx) {
1355 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_OTHER, event);
1356 return 0;
1357 }
1358
1359 if (event->type == PJSIP_EVENT_TSX_STATE_CHANGED) {
1360 switch (tsx->state) {
1361 case PJSIP_TSX_STATE_PROCEEDING:
1362 if (dlg->state != PJSIP_DIALOG_STATE_PROCEEDING) {
1363 /* Change state to PROCEEDING */
1364 dlg_set_state(dlg, PJSIP_DIALOG_STATE_PROCEEDING, event);
1365
1366 /* Notify application. */
1367 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1368 } else {
1369 /* Also notify application. */
1370 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_OTHER, event);
1371 }
1372 break;
1373
1374 case PJSIP_TSX_STATE_COMPLETED:
1375 /* Change dialog state. */
1376 if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200)) {
1377 /* Update remote target, take it from the contact hdr. */
1378 pjsip_contact_hdr *contact;
1379 contact = pjsip_msg_find_hdr(event->src.rdata->msg,
1380 PJSIP_H_CONTACT, NULL);
1381 if (contact) {
1382 dlg->remote.target = pjsip_uri_clone(dlg->pool, contact->uri);
1383 } else {
1384 PJ_LOG(4,(dlg->obj_name,
1385 "Warning: found no Contact hdr in 200/OK"));
1386 }
1387 dlg_set_state(dlg, PJSIP_DIALOG_STATE_CONNECTING, event);
1388 } else if (tsx->status_code==401 || tsx->status_code==407) {
1389 /* Handle Authentication challenge. */
1390 pjsip_tx_data *tdata;
1391 tdata = pjsip_auth_reinit_req( dlg->ua->endpt,
1392 dlg->pool, &dlg->auth_sess,
1393 dlg->cred_count, dlg->cred_info,
1394 tsx->last_tx, event->src.rdata);
1395 if (tdata) {
1396 /* Re-use original request, with a new transaction.
1397 * Need not to worry about CSeq, dialog will take care.
1398 */
1399 pjsip_dlg_send_msg(dlg, tdata);
1400 return 0;
1401 } else {
1402 dlg_set_state(dlg, PJSIP_DIALOG_STATE_DISCONNECTED, event);
1403 }
1404 } else {
1405 dlg_set_state(dlg, PJSIP_DIALOG_STATE_DISCONNECTED, event);
1406 }
1407
1408 /* Notify application. */
1409 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1410
1411 /* Send ACK when dialog is connected. */
1412 if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200)) {
1413 pj_assert(event->src_type == PJSIP_EVENT_RX_MSG);
1414 dlg_on_recv_2xx_invite(dlg, event);
1415 }
1416 break;
1417
1418 case PJSIP_TSX_STATE_TERMINATED:
1419 /*
1420 * Transaction is terminated because of timeout or transport error.
1421 * To let the application go to normal state progression, call the
1422 * callback twice. First is to emulate disconnection, and then call
1423 * again (with state TERMINATED) to destroy the dialog.
1424 */
1425 dlg_set_state(dlg, PJSIP_DIALOG_STATE_DISCONNECTED, event);
1426 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1427
1428 /* The INVITE transaction will be destroyed, so release reference
1429 * to it.
1430 */
1431 dlg->invite_tsx = NULL;
1432
1433 /* We should terminate the dialog now.
1434 * But it's possible that we have other pending transactions (for
1435 * example, outgoing CANCEL is in progress).
1436 * So destroy the dialog only if there's no other transaction.
1437 */
1438 if (dlg->pending_tsx_count == 0) {
1439 dlg_set_state(dlg, PJSIP_DIALOG_STATE_TERMINATED, event);
1440 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1441 dlg_is_terminated = 1;
1442 }
1443 break;
1444
1445 default:
1446 pj_assert(0);
1447 break;
1448 }
1449 } else {
1450 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_OTHER, event);
1451 }
1452 return dlg_is_terminated ? -1 : 0;
1453}
1454
1455/*
1456 * State PROCEEDING for UAS is after the callee send provisional response.
1457 * This function is also called for INCOMING state.
1458 */
1459static int dlg_on_state_proceeding_callee( pjsip_dlg *dlg,
1460 pjsip_transaction *tsx,
1461 pjsip_event *event)
1462{
1463 int dlg_is_terminated = 0;
1464
1465 pj_assert( dlg->invite_tsx != NULL );
1466
1467 if (event->type == PJSIP_EVENT_TSX_STATE_CHANGED &&
1468 event->src_type == PJSIP_EVENT_TX_MSG &&
1469 tsx == dlg->invite_tsx)
1470 {
1471 switch (tsx->state) {
1472 case PJSIP_TSX_STATE_PROCEEDING:
1473 /* Change state to PROCEEDING */
1474 dlg_set_state(dlg, PJSIP_DIALOG_STATE_PROCEEDING, event);
1475
1476 /* Notify application. */
1477 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1478 break;
1479
1480 case PJSIP_TSX_STATE_COMPLETED:
1481 case PJSIP_TSX_STATE_TERMINATED:
1482 /* Change dialog state. */
1483 if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200)) {
1484 dlg_set_state(dlg, PJSIP_DIALOG_STATE_CONNECTING, event);
1485 } else {
1486 dlg_set_state(dlg, PJSIP_DIALOG_STATE_DISCONNECTED, event);
1487 }
1488
1489 /* Notify application. */
1490 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1491
1492 /* If transaction is terminated in non-2xx situation,
1493 * terminate dialog as well. This happens when something unexpected
1494 * occurs, such as transport error.
1495 */
1496 if (tsx->state == PJSIP_TSX_STATE_TERMINATED &&
1497 !PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200))
1498 {
1499 dlg_set_state(dlg, PJSIP_DIALOG_STATE_TERMINATED, event);
1500 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1501 dlg_is_terminated = 1;
1502 }
1503 break;
1504
1505 default:
1506 pj_assert(0);
1507 break;
1508 }
1509
1510 } else if (event->type == PJSIP_EVENT_TSX_STATE_CHANGED &&
1511 event->src_type == PJSIP_EVENT_RX_MSG &&
1512 tsx->method.id == PJSIP_CANCEL_METHOD)
1513 {
1514 pjsip_tx_data *tdata;
1515
1516 /* Check if sequence number matches the pending INVITE. */
1517 if (dlg->invite_tsx==NULL ||
1518 pj_strcmp(&tsx->branch, &dlg->invite_tsx->branch) != 0)
1519 {
1520 PJ_LOG(4, (dlg->obj_name, "Received CANCEL with no matching INVITE"));
1521
1522 /* No matching INVITE transaction found. */
1523 tdata = pjsip_endpt_create_response(dlg->ua->endpt,
1524 event->src.rdata,
1525 PJSIP_SC_CALL_TSX_DOES_NOT_EXIST );
1526 pjsip_tsx_on_tx_msg(tsx, tdata);
1527 return 0;
1528 }
1529
1530 /* Always respond the CANCEL with 200/CANCEL no matter what. */
1531 tdata = pjsip_endpt_create_response(dlg->ua->endpt,
1532 event->src.rdata,
1533 200 );
1534 pjsip_tsx_on_tx_msg( tsx, tdata );
1535
1536 /* Respond the INVITE transaction with 487, only if transaction has
1537 * not completed.
1538 */
1539 if (dlg->invite_tsx->last_tx) {
1540 if (dlg->invite_tsx->status_code < 200) {
1541 tdata = dlg->invite_tsx->last_tx;
1542 tdata->msg->line.status.code = 487;
1543 tdata->msg->line.status.reason = *pjsip_get_status_text(487);
1544 /* Reset packet buffer. */
1545 pjsip_tx_data_invalidate_msg(tdata);
1546 pjsip_tsx_on_tx_msg( dlg->invite_tsx, tdata );
1547 } else {
1548 PJ_LOG(4, (dlg->obj_name, "Received CANCEL with no effect, "
1549 "Transaction already terminated "
1550 "with status %d",
1551 dlg->invite_tsx->status_code));
1552 }
1553 } else {
1554 tdata = pjsip_endpt_create_response(dlg->ua->endpt,
1555 event->src.rdata,
1556 487);
1557 pjsip_tsx_on_tx_msg( dlg->invite_tsx, tdata );
1558 }
1559 } else {
1560 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_OTHER, event);
1561 }
1562
1563 return dlg_is_terminated ? -1 : 0;
1564}
1565
1566static int dlg_on_state_proceeding( pjsip_dlg *dlg,
1567 pjsip_transaction *tsx,
1568 pjsip_event *event)
1569{
1570 if (dlg->role == PJSIP_ROLE_UAC) {
1571 return dlg_on_state_proceeding_caller( dlg, tsx, event );
1572 } else {
1573 return dlg_on_state_proceeding_callee( dlg, tsx, event );
1574 }
1575}
1576
1577static int dlg_on_state_connecting( pjsip_dlg *dlg,
1578 pjsip_transaction *tsx,
1579 pjsip_event *event)
1580{
1581 if (tsx == dlg->invite_tsx) {
1582 if (event->type == PJSIP_EVENT_TSX_STATE_CHANGED &&
1583 (tsx->state == PJSIP_TSX_STATE_TERMINATED ||
1584 tsx->state == PJSIP_TSX_STATE_COMPLETED ||
1585 tsx->state == PJSIP_TSX_STATE_CONFIRMED))
1586 {
1587 if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code, 200)) {
1588 dlg_set_state(dlg, PJSIP_DIALOG_STATE_ESTABLISHED, event);
1589 } else {
1590 /* Probably because we never get the ACK, or transport error
1591 * when sending ACK.
1592 */
1593 dlg_set_state(dlg, PJSIP_DIALOG_STATE_DISCONNECTED, event);
1594 }
1595 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1596 } else {
1597 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_OTHER, event);
1598 }
1599 } else {
1600 /* Handle case when transaction is started when dialog is connecting
1601 * (e.g. BYE requests cross wire.
1602 */
1603 if (event->type == PJSIP_EVENT_TSX_STATE_CHANGED &&
1604 event->src_type == PJSIP_EVENT_RX_MSG &&
1605 tsx->role == PJSIP_ROLE_UAS)
1606 {
1607 pjsip_tx_data *response;
1608
1609 if (tsx->status_code >= 200)
1610 return 0;
1611
1612 if (tsx->method.id == PJSIP_BYE_METHOD) {
1613 /* Set state to DISCONNECTED. */
1614 dlg_set_state(dlg, PJSIP_DIALOG_STATE_DISCONNECTED, event);
1615
1616 /* Notify application. */
1617 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1618
1619 response = pjsip_endpt_create_response( dlg->ua->endpt,
1620 event->src.rdata, 200);
1621 } else {
1622 response = pjsip_endpt_create_response( dlg->ua->endpt, event->src.rdata,
1623 PJSIP_SC_INTERNAL_SERVER_ERROR);
1624 }
1625
1626 if (response)
1627 pjsip_tsx_on_tx_msg(tsx, response);
1628
1629 return 0;
1630 }
1631 }
1632 return 0;
1633}
1634
1635static int dlg_on_state_established( pjsip_dlg *dlg,
1636 pjsip_transaction *tsx,
1637 pjsip_event *event)
1638{
1639 PJ_UNUSED_ARG(tsx)
1640
1641 if (tsx && tsx->method.id == PJSIP_BYE_METHOD) {
1642 /* Set state to DISCONNECTED. */
1643 dlg_set_state(dlg, PJSIP_DIALOG_STATE_DISCONNECTED, event);
1644
1645 /* Notify application. */
1646 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1647
1648 /* Answer with 200/BYE. */
1649 if (event->src_type == PJSIP_EVENT_RX_MSG) {
1650 pjsip_tx_data *tdata;
1651 tdata = pjsip_endpt_create_response(dlg->ua->endpt,
1652 event->src.rdata,
1653 200 );
1654 if (tdata)
1655 pjsip_tsx_on_tx_msg( tsx, tdata );
1656 }
1657 } else if (tsx && event->src_type == PJSIP_EVENT_RX_MSG) {
1658 pjsip_method_e method = event->src.rdata->cseq->method.id;
1659
1660 PJ_TODO(PROPERLY_HANDLE_REINVITATION)
1661
1662 /* Reinvitation. The message may be INVITE or an ACK. */
1663 if (method == PJSIP_INVITE_METHOD) {
1664 if (dlg->invite_tsx && dlg->invite_tsx->status_code < 200) {
1665 /* Section 14.2: A UAS that receives a second INVITE before it
1666 * sends the final response to a first INVITE with a lower
1667 * CSeq sequence number on the same dialog MUST return a 500
1668 * (Server Internal Error) response to the second INVITE and
1669 * MUST include a Retry-After header field with a randomly
1670 * chosen value of between 0 and 10 seconds.
1671 */
1672 pjsip_retry_after_hdr *hdr;
1673 pjsip_tx_data *tdata =
1674 pjsip_endpt_create_response(dlg->ua->endpt,
1675 event->src.rdata, 500);
1676
1677 if (!tdata)
1678 return 0;
1679
1680 /* Add Retry-After. */
1681 hdr = pjsip_retry_after_hdr_create(tdata->pool);
1682 hdr->ivalue = 9;
1683 pjsip_msg_add_hdr(tdata->msg, (pjsip_hdr*)hdr);
1684
1685 /* Send. */
1686 pjsip_tsx_on_tx_msg(tsx, tdata);
1687
1688 return 0;
1689 }
1690
1691 /* Keep this as our current INVITE transaction. */
1692 dlg->invite_tsx = tsx;
1693
1694 /* Create response buffer. */
1695 tsx->last_tx = pjsip_endpt_create_response( dlg->ua->endpt,
1696 event->src.rdata, 100);
1697 pjsip_tx_data_add_ref(tsx->last_tx);
1698
1699 }
1700
1701 /* Notify application. */
1702 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_MID_CALL_REQUEST, event);
1703
1704 } else {
1705 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_OTHER, event);
1706 }
1707
1708 return 0;
1709}
1710
1711static int dlg_on_state_disconnected( pjsip_dlg *dlg,
1712 pjsip_transaction *tsx,
1713 pjsip_event *event)
1714{
1715 PJ_UNUSED_ARG(tsx)
1716
1717 /* Handle case when transaction is started when dialog is disconnected
1718 * (e.g. BYE requests cross wire.
1719 */
1720 if (event->type == PJSIP_EVENT_TSX_STATE_CHANGED &&
1721 event->src_type == PJSIP_EVENT_RX_MSG &&
1722 tsx->role == PJSIP_ROLE_UAS)
1723 {
1724 pjsip_tx_data *response = NULL;
1725
1726 if (tsx->status_code >= 200)
1727 return 0;
1728
1729 if (tsx->method.id == PJSIP_BYE_METHOD) {
1730 response = pjsip_endpt_create_response( dlg->ua->endpt,
1731 event->src.rdata, 200);
1732 } else {
1733 response = pjsip_endpt_create_response( dlg->ua->endpt, event->src.rdata,
1734 PJSIP_SC_INTERNAL_SERVER_ERROR);
1735 }
1736 if (response)
1737 pjsip_tsx_on_tx_msg(tsx, response);
1738
1739 return 0;
1740 }
1741 /* Handle case when outgoing BYE was rejected with 401/407 */
1742 else if (event->type == PJSIP_EVENT_TSX_STATE_CHANGED &&
1743 event->src_type == PJSIP_EVENT_RX_MSG &&
1744 tsx->role == PJSIP_ROLE_UAC)
1745 {
1746 if (tsx->status_code==401 || tsx->status_code==407) {
1747 pjsip_tx_data *tdata;
1748 tdata = pjsip_auth_reinit_req( dlg->ua->endpt, dlg->pool,
1749 &dlg->auth_sess,
1750 dlg->cred_count, dlg->cred_info,
1751 tsx->last_tx, event->src.rdata);
1752 if (tdata) {
1753 pjsip_dlg_send_msg(dlg, tdata);
1754 }
1755 }
1756 }
1757
1758
1759 if (dlg->pending_tsx_count == 0) {
1760 /* Set state to TERMINATED. */
1761 dlg_set_state(dlg, PJSIP_DIALOG_STATE_TERMINATED, event);
1762
1763 /* Notify application. */
1764 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_STATE_CHANGED, event);
1765
1766 return -1;
1767 } else {
1768 dlg_call_dlg_callback(dlg, PJSIP_DIALOG_EVENT_OTHER, event);
1769 }
1770
1771 return 0;
1772}
1773
1774static int dlg_on_state_terminated( pjsip_dlg *dlg,
1775 pjsip_transaction *tsx,
1776 pjsip_event *event)
1777{
1778 PJ_UNUSED_ARG(dlg)
1779 PJ_UNUSED_ARG(tsx)
1780 PJ_UNUSED_ARG(event)
1781
1782 return -1;
1783}
1784