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