nua_session.c 144 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * This file is part of the Sofia-SIP package
 *
 * Copyright (C) 2006 Nokia Corporation.
 *
 * Contact: Pekka Pessi <pekka.pessi@nokia.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 */

/**@CFILE nua_session.c
26
 * @brief SIP session handling
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
 *
 * @author Pekka Pessi <Pekka.Pessi@nokia.com>
 *
 * @date Created: Wed Mar  8 16:17:27 EET 2006 ppessi
 */

#include "config.h"

#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>

#include <assert.h>

42
#include <sofia-sip/su_string.h>
43 44 45
#include <sofia-sip/sip_protos.h>
#include <sofia-sip/sip_status.h>
#include <sofia-sip/sip_util.h>
46
#include <sofia-sip/su_uniqueid.h>
47
#include <sofia-sip/msg_mime_protos.h>
48

49
#define NTA_INCOMING_MAGIC_T struct nua_server_request
50
#define NTA_OUTGOING_MAGIC_T struct nua_client_request
51
#define NTA_RELIABLE_MAGIC_T struct nua_server_request
52 53 54 55 56 57 58 59

#include "nua_stack.h"
#include <sofia-sip/soa.h>

#ifndef SDP_H
typedef struct sdp_session_s sdp_session_t;
#endif

60
/* ---------------------------------------------------------------------- */
61

62 63 64 65 66 67 68 69 70 71 72 73
/** @enum nua_callstate

The states for SIP session established with INVITE.

Initially the call states follow the state of the INVITE transaction. If the
initial INVITE transaction fails, the call is terminated. The status codes
401 and 407 are an exception: if the client (on the left side in the diagram
below) receives them, it enters in #nua_callstate_authenticating state.

If a re-INVITE transaction fails, the result depends on the status code in
failure. The call can return to the ready state, be terminated immediately,
or be terminated gracefully. The proper action to take is determined with
74
sip_response_terminates_dialog().
75 76

@sa @ref nua_call_model, #nua_i_state, nua_invite(), #nua_i_invite
77 78 79 80 81

@par Session State Diagram

@code
  			 +----------+
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
  			 |          |---------------------+
  			 |   Init   |                     |
  			 |          |----------+          |
  			 +----------+          |          |
  			  |        |           |          |
                 --/INVITE|        |INVITE/100 |          |
                          V        V           |          |
     		+----------+      +----------+ |          |
       +--------|          |      |          | |          |
       |  18X +-| Calling  |      | Received | |INVITE/   |
       |   /- | |          |      |          | |  /18X    |
       |      V +----------+      +----------+ V          |
       |   +----------+ |           |     |  +----------+ |
       |---|          | |2XX     -/ |  -/ |  |          | |
       |   | Proceed- | | /-     2XX|  18X|  |  Early   | |INVITE/
       |   |   ing    | |           |     +->|          | |  /200
       |   +----------+ V           V        +----------+ |
       |     |  +----------+      +----------+   | -/     |
       |  2XX|  |          |      |          |<--+ 2XX    |
       |   /-|  | Complet- |      | Complete |<-----------+
       |     +->|   ing    |      |          |------+
       |        +----------+      +----------+      |
       |                  |        |      |         |
       |401,407/     -/ACK|        |ACK/- |timeout/ |
       | /ACK             V        V      | /BYE    |
       |                 +----------+     |         |
       |                 |          |     |         |
       |              +--|  Ready   |     |         |
       |              |  |          |     |         |
       |              |  +----------+     |         |
       |              |       |           |         |
       |         BYE/ |       |-/BYE      |         |BYE/
       V         /200 |       V           |         |/200
  +----------+        |  +----------+     |         |
  |          |        |  |          |     |         |
  |Authentic-|        |  | Terminat-|<----+         |
  |  ating   |        |  |   ing    |               |
  +----------+        |  +----------+               |
                      |       |                     |
                      |       |[23456]XX/-          |
                      |       V                     |
                      |  +----------+               |
                      |  |          |               |
                      +->|Terminated|<--------------+
                         |          |
                         +----------+
128
                              |
129 130 131 132 133
                              V
                         +----------+
        		 |          |
                         |   Init   |
			 |          |
134
          		 +----------+
135 136 137
@endcode
*/

138 139 140
/* ---------------------------------------------------------------------- */
/* Session event usage */

Pekka Pessi's avatar
Pekka Pessi committed
141
/** @internal @brief Session-related state. */
142 143
typedef struct nua_session_usage
{
144
  enum nua_callstate ss_state;		/**< Session status (enum nua_callstate) */
145

146 147
  unsigned        ss_100rel:1;	        /**< Use 100rel, send 183 */
  unsigned        ss_alerting:1;	/**< 180 is sent/received */
148

149 150 151 152
  unsigned        ss_update_needed:2;	/**< Send an UPDATE (do O/A if > 1) */

  unsigned        ss_precondition:1;	/**< Precondition required */

153
  unsigned        ss_reporting:1;       /**< True if reporting state */
154
  unsigned        : 0;
155 156 157 158 159 160 161 162 163 164 165 166 167

  struct session_timer {
    unsigned  interval;		/**< Negotiated expiration time */
    enum nua_session_refresher refresher; /**< Our Negotiated role */

    struct {
      unsigned expires, defaults; /**< Value of Session-Expires (delta) */
      unsigned min_se;	/**< Minimum session expires */
      /** none, local or remote */
      enum nua_session_refresher refresher;
      unsigned    supported:1, require:1, :0;
    } local, remote;
  } ss_timer[1];
168

169
  char const     *ss_reason;	        /**< Reason for termination. */
170 171 172

  /* Offer-Answer status */
  char const     *ss_oa_recv, *ss_oa_sent;
173 174

  /**< Version of user SDP from latest successful O/A */
175
  int ss_sdp_version;
176
} nua_session_usage_t;
177

178 179
static char const Offer[] = "offer", Answer[] = "answer";

180
static char const *nua_session_usage_name(nua_dialog_usage_t const *du);
181
static int nua_session_usage_add(nua_handle_t *nh,
182 183
				 nua_dialog_state_t *ds,
				 nua_dialog_usage_t *du);
184
static void nua_session_usage_remove(nua_handle_t *nh,
185
				     nua_dialog_state_t *ds,
186 187 188
				     nua_dialog_usage_t *du,
				     nua_client_request_t *cr,
				     nua_server_request_t *sr);
189
static void nua_session_usage_refresh(nua_owner_t *,
190
				      nua_dialog_state_t *,
191
				      nua_dialog_usage_t *);
192
static int nua_session_usage_shutdown(nua_owner_t *,
193 194
				      nua_dialog_state_t *,
				      nua_dialog_usage_t *);
195

196 197 198 199 200
static void signal_call_state(nua_handle_t *nh,
			      nua_dialog_state_t *ds,
			      nua_session_usage_t *ss,
			      int status, char const *phrase,
			      enum nua_callstate next_state);
201

202
static int nua_invite_client_should_ack(nua_client_request_t const *cr);
203
static int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags);
204
static int nua_invite_client_complete(nua_client_request_t *cr);
205

206 207
static nua_usage_class const nua_session_usage[1] = {
  {
208
    sizeof (nua_session_usage_t),
209 210 211 212
    sizeof nua_session_usage,
    nua_session_usage_add,
    nua_session_usage_remove,
    nua_session_usage_name,
213
    nua_base_usage_update_params,
214 215 216
    NULL,
    nua_session_usage_refresh,
    nua_session_usage_shutdown
217 218 219 220 221 222 223
  }};

static char const *nua_session_usage_name(nua_dialog_usage_t const *du)
{
  return "session";
}

224 225
static
int nua_session_usage_add(nua_handle_t *nh,
226 227 228
			   nua_dialog_state_t *ds,
			   nua_dialog_usage_t *du)
{
229
  nua_session_usage_t *ss = NUA_DIALOG_USAGE_PRIVATE(du);
230

231 232 233
  if (ds->ds_has_session)
    return -1;
  ds->ds_has_session = 1;
234
  ds->ds_got_session = 1;
235

236 237 238
  ss->ss_timer->local.refresher = nua_any_refresher;
  ss->ss_timer->remote.refresher = nua_any_refresher;

239 240 241
  return 0;
}

242 243
static
void nua_session_usage_remove(nua_handle_t *nh,
244 245 246 247
			      nua_dialog_state_t *ds,
			      nua_dialog_usage_t *du,
			      nua_client_request_t *cr0,
			      nua_server_request_t *sr0)
248
{
249
  nua_session_usage_t *ss = NUA_DIALOG_USAGE_PRIVATE(du);
250
  nua_client_request_t *cr, *cr_next;
251
  nua_server_request_t *sr;
252 253 254 255 256 257 258

  /* Destroy queued INVITE transactions */
  for (cr = ds->ds_cr; cr; cr = cr_next) {
    cr_next = cr->cr_next;

    if (cr->cr_method != sip_method_invite)
      continue;
259

260 261 262
    if (cr == cr0)
      continue;

263 264
    nua_client_request_ref(cr);

265 266 267 268 269 270
    if (nua_invite_client_should_ack(cr)) {
      ss->ss_reporting = 1;
      nua_invite_client_ack(cr, NULL);
      ss->ss_reporting = 0;
    }

271
    if (cr == du->du_cr && cr->cr_orq)
272 273
      continue;

274
    if (cr->cr_status < 200) {
275
      nua_stack_event(nh->nh_nua, nh,
276
		      NULL,
Kai Samposalo's avatar
Kai Samposalo committed
277
		      (enum nua_event_e)cr->cr_event,
278 279 280
		      SIP_481_NO_TRANSACTION,
		      NULL);
    }
281

282
    nua_client_request_remove(cr);
283

284 285
    nua_client_request_unref(cr);

286 287
    cr_next = ds->ds_cr;
  }
288

289 290 291 292
  if (ss->ss_state != nua_callstate_terminated &&
      ss->ss_state != nua_callstate_init &&
      !ss->ss_reporting) {
    int status = 0; char const *phrase = "Terminated";
293 294

    if (cr0)
295 296 297 298
      status = cr0->cr_status, phrase = cr0->cr_phrase ? cr0->cr_phrase : phrase;
    else if (sr0)
      status = sr0->sr_status, phrase = sr0->sr_phrase;

299
    signal_call_state(nh, ds, ss, status, phrase, nua_callstate_terminated);
300 301
  }

302 303 304 305 306 307
  /* Application can respond to BYE after the session usage has terminated */
  for (sr = ds->ds_sr; sr; sr = sr->sr_next) {
    if (sr->sr_usage == du && sr->sr_method == sip_method_bye)
      sr->sr_usage = NULL;
  }

308 309 310 311 312
  ds->ds_has_session = 0;
  nh->nh_has_invite = 0;
  nh->nh_active_call = 0;
  nh->nh_hold_remote = 0;

313 314
  if (ds->ds_soa)
    soa_destroy(ds->ds_soa), ds->ds_soa = NULL;
315
}
316

317 318 319 320 321
static
nua_dialog_usage_t *nua_dialog_usage_for_session(nua_dialog_state_t const *ds)
{
  if (ds == ((nua_handle_t *)NULL)->nh_ds)
    return NULL;
322

323
  return nua_dialog_usage_get(ds, nua_session_usage, NULL);
324 325 326
}

static
327
nua_session_usage_t *nua_session_usage_for_dialog(nua_dialog_state_t const *ds)
328 329 330 331 332 333 334 335 336
{
  nua_dialog_usage_t *du;

  if (ds == ((nua_handle_t *)NULL)->nh_ds)
    return NULL;

  du = nua_dialog_usage_get(ds, nua_session_usage, NULL);

  return (nua_session_usage_t *)nua_dialog_usage_private(du);
337 338
}

339 340 341 342 343 344
/** Zap the session associated with the handle */
static
void nua_session_usage_destroy(nua_handle_t *nh,
			       nua_session_usage_t *ss)
{
  /* Remove usage */
345
  nua_dialog_usage_t *du = nua_dialog_usage_public(ss);
346

347 348 349
  nua_dialog_usage_remove(nh, du->du_dialog, du, NULL, NULL);

  SU_DEBUG_5(("nua(%p): terminated session\n", (void *)nh));
350
}
351

352 353
/* ======================================================================== */
/* INVITE and call (session) processing */
354

355 356 357 358 359 360 361 362
static int session_timer_is_supported(struct session_timer const *t);

static void session_timer_preferences(struct session_timer *t,
				      sip_t const *sip,
				      sip_supported_t const *supported,
				      unsigned expires, int isset,
				      enum nua_session_refresher refresher,
				      unsigned min_se);
363

364 365
static void session_timer_store(struct session_timer *t,
				sip_t const *sip);
366

367 368 369
static int session_timer_check_min_se(msg_t *msg, sip_t *sip,
				      sip_t const *request,
				      unsigned long min_se);
370

371 372 373 374
static int session_timer_add_headers(struct session_timer *t,
				     int initial,
				     msg_t *msg, sip_t *sip);

375
static void session_timer_negotiate(struct session_timer *t, int uas);
376

377
static void session_timer_set(nua_session_usage_t *ss, int uas);
378

379 380 381
static int session_timer_check_restart(nua_client_request_t *cr,
				       int status, char const *phrase,
				       sip_t const *sip);
382

383 384 385
static int nh_referral_check(nua_handle_t *nh, tagi_t const *tags);
static void nh_referral_respond(nua_handle_t *,
				int status, char const *phrase);
386

387 388 389
static int session_get_description(sip_t const *sip,
				   char const **return_sdp,
				   size_t *return_len);
390 391

static
392
int session_include_description(soa_session_t *soa,
393
				int session,
394
				msg_t *msg,
395 396 397
				sip_t *sip);

static
398 399
int session_make_description(su_home_t *home,
			     soa_session_t *soa,
400
			     int session,
401 402 403 404
			     sip_content_disposition_t **return_cd,
			     sip_content_type_t **return_ct,
			     sip_payload_t **return_pl);

405
static
406 407 408
int nua_server_retry_after(nua_server_request_t *sr,
			   int status, char const *phrase,
			   int min, int max);
409

410
/**@fn void nua_invite(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...);
411
 *
412
 * Place a call using SIP @b INVITE method.
413
 *
414 415
 * The INVITE method is used to initiate a call between two parties. The
 * call is also known as <i>SIP session</i>.
416
 *
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
 * At SIP level the session is represented as @e Dialog, which is a
 * peer-to-peer association between two SIP User-Agents. The dialog is
 * established by a successful 2XX response to the INVITE. The dialog is
 * terminated by BYE transaction, which application can initiate with
 * nua_bye() call.
 *
 * An @e early @e dialog is established by an preliminary response
 * (101..199), such as <i>180 Ringing</i>. An early dialog is terminated
 * with an error response with response code in range 300...699.
 *
 * The media session belonging to the SIP session is usually represented by
 * SDP, Session Description Protocol. The media session it is usually
 * established during the call set-up with procedure known as SDP
 * Offer/Answer exchange, defined by @RFC3264. See <b>Media Session
 * Handling</b> below for details.
432 433 434 435
 *
 * @param nh              Pointer to operation handle
 * @param tag, value, ... List of tagged parameters
 *
436
 * @return
437 438 439 440
 *    nothing
 *
 * @par Events:
 *    #nua_r_invite \n
441
 *    #nua_i_state (#nua_i_active, #nua_i_terminated) \n
442 443 444
 *    #nua_i_media_error \n
 *    #nua_i_fork \n
 *
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
 * @par Tags:
 *   NUTAG_AUTH_CACHE() \n
 *   NUTAG_AUTOACK() \n
 *   NUTAG_AUTOANSWER() \n
 *   NUTAG_EARLY_MEDIA() \n
 *   NUTAG_ENABLEINVITE() \n
 *   NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR() \n
 *   NUTAG_INVITE_TIMER() \n
 *   NUTAG_MEDIA_ENABLE() \n
 *   NUTAG_MEDIA_FEATURES() \n
 *   NUTAG_MIN_SE() \n
 *   NUTAG_RETRY_COUNT() \n
 *   NUTAG_SERVICE_ROUTE_ENABLE() \n
 *   NUTAG_SESSION_REFRESHER() \n
 *   NUTAG_SESSION_TIMER() \n
 *   NUTAG_SOA_NAME() \n
 *   NUTAG_UPDATE_REFRESH() \n
 *
463 464 465 466 467
 * @par Populating SIP Request Message with Tagged Arguments
 * The tagged arguments can be used to pass values for any SIP headers to
 * the stack. When the INVITE message (or any other SIP message) is created,
 * the tagged values saved with nua_handle() are used first, next the tagged
 * values given with the operation (nua_invite()) are added.
468 469
 *
 * @par
470 471
 * When multiple tags for the same header are specified, the behaviour
 * depends on the header type. If only a single header field can be included
472
 * in a SIP message, the latest non-NULL value is used, e.g., @Subject.
473 474 475
 * However, if the SIP header can consist of multiple lines or header fields
 * separated by comma, e.g., @Accept, all the tagged
 * values are concatenated.
476
 *
477
 * @par
478 479 480
 * However, if a tag value is #SIP_NONE (-1 casted as a void pointer), the
 * values from previous tags are ignored.
 *
481
 * @par
482 483 484 485
 * Next, values previously set with nua_set_params() or nua_set_hparams()
 * are used: @Allow, @Supported, @Organization, and @UserAgent headers are
 * added to the request if they are not already set.
 *
486
 * @par
487 488
 * Now, the target URI for the request needs to be determined.
 *
489
 * @par
490 491 492
 * For initial INVITE requests, values from tags are used. If NUTAG_URL() is
 * given, it is used as target URI. Otherwise, if SIPTAG_TO() is given, it
 * is used as target URI. If neither is given, the complete request line
493
 * already specified using SIPTAG_REQUEST() or SIPTAG_REQUEST_STR() is used.
494 495
 * If none of the tags above are given, an internal error is returned to the
 * application. At this point, the target URI is stored in the request line,
496
 * together with method name ("INVITE") and protocol version ("SIP/2.0").
497
 * The initial dialog information is also created: @CallID, @CSeq headers
498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
 * are generated, if they do not exist, and an unique tag is added to @From
 * header.
 *
 * @par
 * For the initial INVITE requests, the @Route headers specified by
 * SIPTAG_ROUTE()/SIPTAG_ROUTER_STR() tags in nua_handle() and nua_invite()
 * calls are inserted to the request. Next the initial route set specified
 * by NUTAG_INITIAL_ROUTE()/NUTAG_INITIAL_ROUTE_STR() tags is prepended to
 * the route. Finally (unless NUTAG_SERVICE_ROUTE_ENABLE(0) is used) the
 * @ServiceRoute set received from the registrar is also appended to the
 * route set of the initial request message.
 *
 * @par
 * Next, the stack generates a @Contact header for the request (Unless the
 * application already gave a @Contact header or it does not want to use
 * @Contact and indicates that by including SIPTAG_CONTACT(NULL) or
 * SIPTAG_CONTACT(SIP_NONE) in the tagged parameters.) If the application
 * has a registration active, the @Contact header used with registration is
 * used. Otherwise, the @Contact header is generated from the local IP
 * address and port number, taking also the values from NUTAG_M_DISPLAY(),
 * NUTAG_M_FEATURES(), NUTAG_M_PARAMS(), and NUTAG_M_USERNAME().
519
 *
520
 * @par
521 522 523
 * For in-dialog INVITE (re-INVITE), the request URI is taken from the
 * @Contact header received from the remote party during the dialog
 * establishment. Also, the @CallID and @CSeq headers and @From and @To tags
524
 * are generated based on the dialog information and added to the request.
525 526 527
 * If the dialog has a route (set by @RecordRoute headers), it is added to
 * the request, too.
 *
528
 * @par
529 530
 * @MaxForwards header (with default value set by NTATAG_MAX_FORWARDS()) is
 * also added now, if it does not exist.
531
 *
532
 * @par
533 534
 * The INVITE request message created by nua_invite() operation is saved as
 * a template for automatic re-INVITE requests sent by the session timer
535 536 537 538 539
 * ("timer") feature (see NUTAG_SESSION_TIMER() for more details). Please
 * note that the template message is not used when ACK, PRACK, UPDATE or
 * INFO requests are created (however, these requests will include
 * dialog-specific headers like @To, @From, and @CallID as well as
 * preference headers @Allow, @Supported, @UserAgent, @Organization).
540
 *
541 542
 * @par Tags Related to SIP Headers and Request-URI
 *    NUTAG_URL(), SIPTAG_REQUEST(), SIPTAG_REQUEST_STR() \n
543 544
 *    NUTAG_INITIAL_ROUTE(), NUTAG_INITIAL_ROUTE_STR(),
 *    SIPTAG_ROUTE(), SIPTAG_ROUTE_STR(),
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
 *    NUTAG_SERVICE_ROUTE_ENABLE() \n
 *    SIPTAG_MAX_FORWARDS(), SIPTAG_MAX_FORWARDS_STR() \n
 *    SIPTAG_PROXY_REQUIRE(), SIPTAG_PROXY_REQUIRE_STR() \n
 *    SIPTAG_FROM(), SIPTAG_FROM_STR() \n
 *    SIPTAG_TO(), SIPTAG_TO_STR() \n
 *    SIPTAG_CALL_ID(), SIPTAG_CALL_ID_STR() \n
 *    SIPTAG_CSEQ(), SIPTAG_CSEQ_STR()
 *    (note that @CSeq value is incremented if request gets retried)\n
 *    SIPTAG_CONTACT(), SIPTAG_CONTACT_STR() \n
 *    SIPTAG_REQUEST_DISPOSITION(), SIPTAG_REQUEST_DISPOSITION_STR() \n
 *    SIPTAG_ACCEPT_CONTACT(), SIPTAG_ACCEPT_CONTACT_STR() \n
 *    SIPTAG_REJECT_CONTACT(), SIPTAG_REJECT_CONTACT_STR() \n
 *    SIPTAG_EXPIRES(), SIPTAG_EXPIRES_STR() \n
 *    SIPTAG_DATE(), SIPTAG_DATE_STR() \n
 *    SIPTAG_TIMESTAMP(), SIPTAG_TIMESTAMP_STR() \n
 *    SIPTAG_SUBJECT(), SIPTAG_SUBJECT_STR() \n
 *    SIPTAG_PRIORITY(), SIPTAG_PRIORITY_STR() \n
 *    SIPTAG_CALL_INFO(), SIPTAG_CALL_INFO_STR() \n
 *    SIPTAG_ORGANIZATION(), SIPTAG_ORGANIZATION_STR() \n
 *    NUTAG_USER_AGENT(), SIPTAG_USER_AGENT() and SIPTAG_USER_AGENT_STR() \n
 *    SIPTAG_IN_REPLY_TO(), SIPTAG_IN_REPLY_TO_STR() \n
 *    SIPTAG_ACCEPT(), SIPTAG_ACCEPT_STR() \n
 *    SIPTAG_ACCEPT_ENCODING(), SIPTAG_ACCEPT_ENCODING_STR() \n
 *    SIPTAG_ACCEPT_LANGUAGE(), SIPTAG_ACCEPT_LANGUAGE_STR() \n
 *    NUTAG_ALLOW(), SIPTAG_ALLOW(), and SIPTAG_ALLOW_STR() \n
 *    NUTAG_EARLY_MEDIA(), SIPTAG_REQUIRE(), and SIPTAG_REQUIRE_STR() \n
 *    NUTAG_SUPPORTED(), SIPTAG_SUPPORTED(), and SIPTAG_SUPPORTED_STR() \n
 *    SIPTAG_ALLOW_EVENTS(), SIPTAG_ALLOW_EVENTS_STR() \n
 *    SIPTAG_PROXY_AUTHORIZATION(), SIPTAG_PROXY_AUTHORIZATION_STR() \n
 *    SIPTAG_AUTHORIZATION(), SIPTAG_AUTHORIZATION_STR() \n
 *    SIPTAG_REFERRED_BY(), SIPTAG_REFERRED_BY_STR() \n
 *    SIPTAG_REPLACES(), SIPTAG_REPLACES_STR() \n
577
 *    NUTAG_SESSION_TIMER(), NUTAG_SESSION_REFRESHER(),
578 579 580 581 582 583 584 585 586 587 588 589 590
 *    SIPTAG_SESSION_EXPIRES(), SIPTAG_SESSION_EXPIRES_STR() \n
 *    NUTAG_MIN_SE(), SIPTAG_MIN_SE(), SIPTAG_MIN_SE_STR() \n
 *    SIPTAG_SECURITY_CLIENT(), SIPTAG_SECURITY_CLIENT_STR() \n
 *    SIPTAG_SECURITY_VERIFY(), SIPTAG_SECURITY_VERIFY_STR() \n
 *    SIPTAG_PRIVACY(), SIPTAG_PRIVACY_STR() \n
 *    SIPTAG_MIME_VERSION(), SIPTAG_MIME_VERSION_STR() \n
 *    SIPTAG_CONTENT_TYPE(), SIPTAG_CONTENT_TYPE_STR() \n
 *    SIPTAG_CONTENT_ENCODING(), SIPTAG_CONTENT_ENCODING_STR() \n
 *    SIPTAG_CONTENT_LANGUAGE(), SIPTAG_CONTENT_LANGUAGE_STR() \n
 *    SIPTAG_CONTENT_DISPOSITION(), SIPTAG_CONTENT_DISPOSITION_STR() \n
 *    SIPTAG_HEADER(), SIPTAG_HEADER_STR() \n
 *    SIPTAG_PAYLOAD(), SIPTAG_PAYLOAD_STR() \n
 *
591
 * @par SDP Handling
592 593 594
 * By default the nua_invite() uses an @ref soa_session_t "SOA media
 * session" object to take care of the Offer/Answer exchange. The SOA can
 * be disabled with tag NUTAG_MEDIA_ENABLE(0).
595
 *
596
 * @par
597 598
 * The SDP description of the
 * @ref soa_session_t "soa media session" is included in the INVITE request
599
 * as a message body.
600 601 602
 * The SDP in the message body of the 1XX or 2XX response message is
 * interpreted as an answer, given to the @ref soa_session_t "soa media
 * session" object for processing.
603 604
 *
 * @bug If the INVITE request already contains a message body, SDP is not
605 606 607 608 609 610
 * added.  Also, if the response contains a multipart body, it is not parsed.
 *
 * @par Tags Related to SDP Management and Offer/Answer Model:
 *    NUTAG_MEDIA_ENABLE(), \n
 *    NUTAG_INCLUDE_EXTRA_SDP(), \n
 *    SOATAG_HOLD(), SOATAG_AF(), SOATAG_ADDRESS(),
611 612
 *    SOATAG_ORDERED_USER(), SOATAG_REUSE_REJECTED(),
 *    SOATAG_RTP_SELECT(), SOATAG_RTP_SORT(), SOATAG_RTP_MISMATCH(),
613 614 615 616 617 618 619 620 621 622 623 624 625
 *    SOATAG_AUDIO_AUX(), \n
 *    SOATAG_USER_SDP() or SOATAG_USER_SDP_STR() \n
 *
 * @par Alternative Call Models
 * In addition to the basic SIP call model described in @RFC3261 and
 * @RFC3264, the early media model described in @RFC3262 is available. The
 * use of 100rel and early media can be use can be forced with
 * NUTAG_EARLY_MEDIA(1).
 *
 * Also, the "precondition" call model described in @RFC3312 is supported at
 * SIP level, that is, the SIP PRACK and UPDATE requests are sent if
 * "precondition" is added to the @Require header in the INVITE request.
 *
626
 * Optionally
627 628
 * - uses early media if NUTAG_EARLY_MEDIA() tag is used with non zero-value
 * - media parameters can be set by SOA tags
629
 * - nua_invite() can be used to change status of an existing call:
630 631
 *   - #SOATAG_HOLD tag can be used to list the media that will be put on hold,
 *     the value "*" sets all the media beloginging to the session on hold
632 633 634 635 636 637
 *
 * @par Authentication
 * The INVITE request may need authentication. Each proxy or server
 * requiring authentication can respond with 401 or 407 response. The
 * nua_authenticate() operation stores authentication information (username
 * and password) to the handle, and stack tries to authenticate all the rest
638 639
 * of the requests (e.g., PRACK, ACK, UPDATE, re-INVITE, BYE) using the
 * stored username and password.
640
 *
641 642
 * @sa @ref nua_call_model, #nua_r_invite, #nua_i_state, \n
 *     nua_handle_has_active_call() \n
643 644 645 646 647
 *     nua_handle_has_call_on_hold()\n
 *     nua_handle_has_invite() \n
 *     nua_authenticate() \n
 *     nua_prack() \n
 *     nua_update() \n
648
 *     nua_info() \n
649 650
 *     nua_cancel() \n
 *     nua_bye() \n
651
 *     #nua_i_invite, nua_respond()
652 653
 */

654 655 656
/* Tags not implemented
 *    NUTAG_REFER_PAUSE() \n
 */
657

658
static int nua_invite_client_init(nua_client_request_t *cr,
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
				  msg_t *msg, sip_t *sip,
				  tagi_t const *tags);
static int nua_invite_client_request(nua_client_request_t *cr,
				     msg_t *msg, sip_t *sip,
				     tagi_t const *tags);
static int nua_invite_client_preliminary(nua_client_request_t *cr,
					 int status, char const *phrase,
					 sip_t const *sip);
static int nua_invite_client_response(nua_client_request_t *cr,
				      int status, char const *phrase,
				      sip_t const *sip);
static int nua_session_client_response(nua_client_request_t *cr,
				       int status, char const *phrase,
				       sip_t const *sip);
static int nua_invite_client_report(nua_client_request_t *cr,
				    int status, char const *phrase,
				    sip_t const *sip,
				    nta_outgoing_t *orq,
				    tagi_t const *tags);

679
nua_client_methods_t const nua_invite_client_methods = {
680 681 682
  SIP_METHOD_INVITE,		/* crm_method, crm_method_name */
  0,				/* crm_extra */
  {				/* crm_flags */
683 684 685 686
    /* create_dialog */ 1,
    /* in_dialog */ 1,
    /* target refresh */ 1
  },
687 688 689 690 691 692 693 694
  NULL,				/* crm_template */
  nua_invite_client_init,	/* crm_init */
  nua_invite_client_request,	/* crm_send */
  session_timer_check_restart,	/* crm_check_restart */
  nua_invite_client_response,	/* crm_recv */
  nua_invite_client_preliminary, /* crm_preliminary */
  nua_invite_client_report,	/* crm_report */
  nua_invite_client_complete,	/* crm_complete */
695 696
};

697 698 699 700
extern nua_client_methods_t const nua_bye_client_methods;
extern nua_client_methods_t const nua_cancel_client_methods;
extern nua_client_methods_t const nua_update_client_methods;
extern nua_client_methods_t const nua_prack_client_methods;
701 702 703 704 705

int nua_stack_invite(nua_t *nua, nua_handle_t *nh, nua_event_t e,
		     tagi_t const *tags)
{
  return nua_client_create(nh, e, &nua_invite_client_methods, tags);
706 707
}

708
static int nua_invite_client_init(nua_client_request_t *cr,
709 710
				  msg_t *msg, sip_t *sip,
				  tagi_t const *tags)
711
{
712
  nua_handle_t *nh = cr->cr_owner;
713
  nua_dialog_usage_t *du;
714
  nua_session_usage_t *ss;
715

716
  cr->cr_usage = du = nua_dialog_usage_for_session(nh->nh_ds);
717
  /* Errors returned by nua_invite_client_init()
718
     do not change the session state */
719 720 721
  cr->cr_neutral = 1;

  if (nh_is_special(nh) ||
722 723 724 725
      nua_stack_set_handle_special(nh, nh_has_invite, nua_i_error))
    return nua_client_return(cr, 900, "Invalid handle for INVITE", msg);
  else if (nh_referral_check(nh, tags) < 0)
    return nua_client_return(cr, 900, "Invalid referral", msg);
726

727 728 729 730 731 732 733
  if (du) {
    nua_server_request_t *sr;
    for (sr = nh->nh_ds->ds_sr; sr; sr = sr->sr_next)
      /* INVITE in progress? */
      if (sr->sr_usage == du && sr->sr_method == sip_method_invite &&
	  nua_server_request_is_pending(sr))
	return nua_client_return(cr, SIP_491_REQUEST_PENDING, msg);
734
    cr->cr_initial = 0;
735
  }
736
  else {
737
    du = nua_dialog_usage_add(nh, nh->nh_ds, nua_session_usage, NULL);
738 739
    cr->cr_initial = 1;
  }
740

741 742
  if (!du)
    return -1;
743

744 745 746 747 748
  ss = nua_dialog_usage_private(du);

  if (ss->ss_state >= nua_callstate_terminating)
    return nua_client_return(cr, 900, "Session is terminating", msg);

749 750
  if (nua_client_bind(cr, du) < 0)
    return nua_client_return(cr, 900, "INVITE already in progress", msg);
751

752
  cr->cr_neutral = 0;
753 754 755

  session_timer_preferences(ss->ss_timer,
			    sip,
756
			    NH_PGET(nh, supported),
757
			    NH_PGET(nh, session_timer),
758 759 760
			    NUA_PISSET(nh->nh_nua, nh, session_timer),
			    NH_PGET(nh, refresher),
			    NH_PGET(nh, min_se));
761

762 763
  return 0;
}
764

765 766 767 768 769 770
static int nua_invite_client_request(nua_client_request_t *cr,
				     msg_t *msg, sip_t *sip,
				     tagi_t const *tags)
{
  nua_handle_t *nh = cr->cr_owner;
  nua_dialog_usage_t *du = cr->cr_usage;
771
  nua_dialog_state_t *ds = du->du_dialog;
772
  nua_session_usage_t *ss;
773 774
  int offer_sent = 0, retval;
  sip_time_t invite_timeout;
775

776
  if (du == NULL)		/* Call terminated */
777
    return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg);
778

779 780
  ss = NUA_DIALOG_USAGE_PRIVATE(du);

781
  if (ss->ss_state >= nua_callstate_terminating || du->du_shutdown)
782 783
    return nua_client_return(cr, 900, "Session is terminating", msg);

784 785 786
  invite_timeout = NH_PGET(nh, invite_timeout);
  if (invite_timeout == 0)
    invite_timeout = UINT_MAX;
787
  /* Send CANCEL if we don't get response within timeout*/
788
  /* nua_dialog_usage_set_expires(du, invite_timeout); Xyzzy */
789
  nua_dialog_usage_reset_refresh(du);
790

791
  /* Add session timer headers */
792 793 794
  if (session_timer_is_supported(ss->ss_timer))
    session_timer_add_headers(ss->ss_timer, ss->ss_state == nua_callstate_init,
			      msg, sip);
795

796 797 798 799
  ss->ss_100rel = NH_PGET(nh, early_media);
  ss->ss_precondition = sip_has_feature(sip->sip_require, "precondition");
  if (ss->ss_precondition)
    ss->ss_update_needed = ss->ss_100rel = 1;
800

801 802
  if (ds->ds_soa) {
    soa_init_offer_answer(ds->ds_soa);
803

804
    if (soa_is_delayed_offer(ds->ds_soa))
805
      offer_sent = 0;
806 807 808
    else if (sip->sip_payload)
      /* Kludge, we should probably use multipart */
      offer_sent = 0;
809
    else if (soa_generate_offer(ds->ds_soa, 0, NULL) < 0)
810
      return -1;
811 812 813
    else
      offer_sent = 1;

814
    if (offer_sent > 0 &&
815
	session_include_description(ds->ds_soa, 1, msg, sip) < 0)
816
      return nua_client_return(cr, 900, "Internal media error", msg);
817

818 819 820 821 822
    if (NH_PGET(nh, media_features) &&
	!nua_dialog_is_established(nh->nh_ds) &&
	!sip->sip_accept_contact && !sip->sip_reject_contact) {
      sip_accept_contact_t ac[1];
      sip_accept_contact_init(ac);
823

824
      ac->cp_params = (msg_param_t *)
825
	soa_media_features(ds->ds_soa, 1, msg_home(msg));
826

827 828 829 830
      if (ac->cp_params) {
	msg_header_replace_param(msg_home(msg), ac->cp_common, "explicit");
	sip_add_dup(msg, sip, (sip_header_t *)ac);
      }
831
    }
832
  }
833 834 835
  else {
    offer_sent = session_get_description(sip, NULL, NULL);
  }
836

837 838 839 840
  retval = nua_base_client_trequest(cr, msg, sip,
				    NTATAG_REL100(ss->ss_100rel),
				    TAG_NEXT(tags));
  if (retval == 0) {
841 842
    if ((cr->cr_offer_sent = offer_sent))
      ss->ss_oa_sent = Offer;
843

844
    if (!cr->cr_restarting) /* Restart logic calls nua_invite_client_report */
845 846
      signal_call_state(nh, ds, ss, 0, "INVITE sent",
			nua_callstate_calling);
847
  }
848

849 850
  return retval;
}
851

852 853 854 855 856 857
static int nua_invite_client_response(nua_client_request_t *cr,
				      int status, char const *phrase,
				      sip_t const *sip)
{
  nua_dialog_usage_t *du = cr->cr_usage;
  nua_session_usage_t *ss = nua_dialog_usage_private(du);
858
  int uas;
859

860 861
  if (ss == NULL || sip == NULL) {
    /* Xyzzy */
862
  }
863 864
  else if (status < 300) {
    du->du_ready = 1;
865

866 867 868
    if (session_timer_is_supported(ss->ss_timer))
      session_timer_store(ss->ss_timer, sip);

869
    session_timer_set(ss, uas = 0);
870
  }
871

872 873
  return nua_session_client_response(cr, status, phrase, sip);
}
874

875 876 877 878 879 880 881
static int nua_invite_client_preliminary(nua_client_request_t *cr,
					 int status, char const *phrase,
					 sip_t const *sip)
{
  nua_handle_t *nh = cr->cr_owner;
  nua_dialog_usage_t *du = cr->cr_usage;
  nua_session_usage_t *ss = nua_dialog_usage_private(du);
882

883
  assert(sip);
884 885 886 887 888 889 890 891 892

  if (ss && sip && sip->sip_rseq) {
    /* Handle 100rel responses */
    sip_rseq_t *rseq = sip->sip_rseq;

    /* Establish early dialog - we should fork here */
    if (!nua_dialog_is_established(nh->nh_ds)) {
      nta_outgoing_t *tagged;

893
      nua_dialog_uac_route(nh, nh->nh_ds, sip, 1, 1);
894
      nua_dialog_store_peer_info(nh, nh->nh_ds, sip);
895

896 897 898 899 900 901 902 903 904 905 906 907
      /* Tag the INVITE request */
      tagged = nta_outgoing_tagged(cr->cr_orq,
				   nua_client_orq_response, cr,
				   sip->sip_to->a_tag, sip->sip_rseq);
      if (tagged) {
	nta_outgoing_destroy(cr->cr_orq), cr->cr_orq = tagged;
      }
      else {
	cr->cr_graceful = 1;
	ss->ss_reason = "SIP;cause=500;text=\"Cannot Create Early Dialog\"";
      }
    }
908

909
    if (!rseq) {
910
      SU_DEBUG_5(("nua(%p): 100rel missing RSeq\n", (void *)nh));
911 912
    }
    else if (nta_outgoing_rseq(cr->cr_orq) > rseq->rs_response) {
913
      SU_DEBUG_5(("nua(%p): 100rel bad RSeq %u (got %u)\n", (void *)nh,
914 915 916 917 918
		  (unsigned)rseq->rs_response,
		  nta_outgoing_rseq(cr->cr_orq)));
      return 1;    /* Do not send event */
    }
    else if (nta_outgoing_setrseq(cr->cr_orq, rseq->rs_response) < 0) {
919
      SU_DEBUG_1(("nua(%p): cannot set RSeq %u\n", (void *)nh,
920 921 922 923 924
		  (unsigned)rseq->rs_response));
      cr->cr_graceful = 1;
      ss->ss_reason = "SIP;cause=400;text=\"Bad RSeq\"";
    }
  }
925

926
  return nua_session_client_response(cr, status, phrase, sip);
927 928
}

929 930 931 932
/** Process response to a session request (INVITE, PRACK, UPDATE) */
static int nua_session_client_response(nua_client_request_t *cr,
				       int status, char const *phrase,
				       sip_t const *sip)
933
{
934 935
  nua_handle_t *nh = cr->cr_owner;
  nua_dialog_usage_t *du = cr->cr_usage;
936
  nua_dialog_state_t *ds = du->du_dialog;
937 938 939 940
  nua_session_usage_t *ss = nua_dialog_usage_private(du);

  char const *sdp = NULL;
  size_t len;
941 942
  char const *received = NULL;

943 944
#define LOG3(m) \
  SU_DEBUG_3(("nua(%p): %s: %s %s in %u %s\n", \
945
	      (void *)nh, cr->cr_method_name, (m), \
946 947 948
	      received ? received : "SDP", status, phrase))
#define LOG5(m) \
  SU_DEBUG_5(("nua(%p): %s: %s %s in %u %s\n", \
949
	      (void *)nh, cr->cr_method_name, (m), received, status, phrase))
950

951 952 953 954 955 956 957
  if (!ss || 300 <= status || !session_get_description(sip, &sdp, &len))
    return nua_base_client_response(cr, status, phrase, sip, NULL);

  if (cr->cr_offer_sent) {
    /* case 1: answer to our offer? */
    int new_answer, previous_answer = cr->cr_answer_recv;

958
    cr->cr_answer_recv = status;
959
    received = Answer;
960

961
    if (ds->ds_soa == NULL) {
962
      LOG5("got SDP");
963 964 965 966
      goto response;
    }

    if (previous_answer && status < 200) {
967
      /* Ignore extra answers in provisional responses */
968 969 970 971 972 973
      LOG5("ignoring extra");
      sdp = NULL;
      received = NULL;
      goto response;
    }

974
    new_answer = soa_set_remote_sdp(ds->ds_soa, NULL, sdp, len);
975
    if (new_answer < 0) {
976 977 978 979
      LOG3("error parsing SDP");
      sdp = NULL;
      cr->cr_graceful = 1;
      ss->ss_reason = "SIP;cause=400;text=\"Malformed Session Description\"";
980
      goto response;
981
    }
982 983 984 985 986 987 988 989 990 991

    if (previous_answer) {
      if (!new_answer) {
	/* Ignore duplicate answers */
	LOG5("ignoring duplicate");
	sdp = NULL;
	received = NULL;
	goto response;
      }
      else {
992 993 994
	if (soa_init_offer_answer(ds->ds_soa) < 0 ||
	    soa_generate_offer(ds->ds_soa, 1, NULL) < 0 ||
	    soa_set_remote_sdp(ds->ds_soa, NULL, sdp, len) < 0) {
995 996 997 998 999 1000 1001
	  LOG5("error reinitializing session");
	  sdp = NULL;
	  goto response;
	}
      }
    }

1002
    if (soa_process_answer(ds->ds_soa, NULL) < 0) {
1003 1004 1005 1006
      LOG5("error processing SDP");
      /* XXX */
      sdp = NULL;
    }
1007
    else if (soa_activate(ds->ds_soa, NULL) < 0) {
1008 1009
      /* XXX - what about errors? */
      LOG3("error activating media after");
1010 1011
    }
    else {
1012
      ss->ss_sdp_version = soa_get_user_version(ds->ds_soa);
1013
      LOG5("processed SDP");
1014
    }
1015 1016 1017 1018 1019 1020 1021
  }
  else if (cr->cr_method != sip_method_invite) {
    /* If non-invite request did not have offer, ignore SDP in response */
    LOG3("ignoring extra");
    sdp = NULL;
  }
  else {
1022
    /* case 2: new offer */
1023
    cr->cr_offer_recv = 1, cr->cr_answer_sent = 0;
1024
    received = Offer;
1025

1026
    if (ds->ds_soa && soa_set_remote_sdp(ds->ds_soa, NULL, sdp, len) < 0) {
1027 1028 1029 1030
      LOG3("error parsing SDP");
      sdp = NULL;
      cr->cr_graceful = 1;
      ss->ss_reason = "SIP;cause=400;text=\"Malformed Session Description\"";
1031
    }
1032
    else
1033
      LOG5("got SDP");
1034
  }
1035

1036 1037
 response:
  if (received)
1038
    ss->ss_oa_recv = received;
1039

1040
  if (sdp && ds->ds_soa)
1041
    return nua_base_client_tresponse(cr, status, phrase, sip,
1042
				     NH_REMOTE_MEDIA_TAGS(1, ds->ds_soa),
1043 1044 1045 1046
				     TAG_END());
  else
    return nua_base_client_response(cr, status, phrase, sip, NULL);
}
1047

1048 1049 1050 1051 1052 1053 1054
static int nua_invite_client_report(nua_client_request_t *cr,
				    int status, char const *phrase,
				    sip_t const *sip,
				    nta_outgoing_t *orq,
				    tagi_t const *tags)
{
  nua_handle_t *nh = cr->cr_owner;
1055
  nua_dialog_state_t *ds;
1056 1057
  nua_dialog_usage_t *du = cr->cr_usage;
  nua_session_usage_t *ss = nua_dialog_usage_private(du);
1058
  msg_t *response = nta_outgoing_getresponse(orq);
1059
  enum nua_callstate next_state;
1060
  int error;
1061

1062
  nh_referral_respond(nh, status, phrase); /* XXX - restarting after 401/407 */
1063

1064
  nua_stack_event(nh->nh_nua, nh,
1065
		  response,
Kai Samposalo's avatar
Kai Samposalo committed
1066
		  (enum nua_event_e)cr->cr_event,
1067
		  status, phrase,
1068
		  tags);
1069

1070 1071
  if (cr->cr_waiting)
    /* Do not report call state change if waiting for restart */
1072
    return 1;
1073

1074
  if (ss == NULL) {
1075
    signal_call_state(nh, NULL, NULL, status, phrase, nua_callstate_terminated);
1076 1077 1078
    return 1;
  }

1079 1080
  ds = du->du_dialog;

1081 1082
  ss->ss_reporting = 1;

1083
  if (cr->cr_neutral) {
1084
    signal_call_state(nh, ds, ss, status, phrase, ss->ss_state);
1085 1086
    ss->ss_reporting = 0;
    return 1;
1087
  }
1088

1089
  response = msg_ref(response); /* Keep reference to contents of sip */
1090

1091 1092 1093
  if (orq != cr->cr_orq && cr->cr_orq) {	/* Being restarted */
    next_state = nua_callstate_calling;
  }
1094 1095
  else if (status < 300 && cr->cr_graceful) {
    next_state = nua_callstate_terminating;
1096
    if (200 <= status)
1097
      nua_invite_client_ack(cr, NULL);
1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108
  }
  else if (du->du_shutdown) {
    if (200 <= status && status < 300)
      nua_invite_client_ack(cr, NULL);
    if (status < 300 && ss->ss_state <= nua_callstate_terminating)
      next_state = nua_callstate_terminating;
    else
      next_state = nua_callstate_terminated;
  }
  else if (status == 100) {
    next_state = nua_callstate_calling;
1109 1110 1111
  }
  else if (status < 200) {
    next_state = nua_callstate_proceeding;
1112

1113
    if (sip && sip->sip_rseq &&
1114
	!SIP_IS_ALLOWED(NH_PGET(nh, appl_method), sip_method_prack)) {
1115 1116 1117 1118 1119 1120 1121 1122
      sip_rack_t rack[1];

      sip_rack_init(rack);
      rack->ra_response    = sip->sip_rseq->rs_response;
      rack->ra_cseq        = sip->sip_cseq->cs_seq;
      rack->ra_method      = sip->sip_cseq->cs_method;
      rack->ra_method_name = sip->sip_cseq->cs_method_name;

1123
      error = nua_client_tcreate(nh, nua_r_prack, &nua_prack_client_methods,
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
				 SIPTAG_RACK(rack),
				 TAG_END());
      if (error < 0) {
	cr->cr_graceful = 1;
	next_state = nua_callstate_terminating;
      }
    }
  }
  else if (status < 300) {
    next_state = nua_callstate_completing;
  }
  else if (cr->cr_terminated) {
    next_state = nua_callstate_terminated;
  }
  else if (cr->cr_graceful && ss->ss_state >= nua_callstate_completing) {
    next_state = nua_callstate_terminating;
1140 1141
  }
  else {
1142
    next_state = nua_callstate_init;
1143 1144
  }

1145
  if (next_state == nua_callstate_calling) {
1146 1147
    if (sip && sip->sip_status && sip->sip_status->st_status == 100) {
      ss->ss_reporting = 0;
1148
      return 1;
1149
    }
1150
  }
1151

1152 1153
  if (next_state == nua_callstate_completing) {
    if (NH_PGET(nh, auto_ack) ||
1154 1155
	/* Auto-ACK response to re-INVITE when media is enabled
	   and auto_ack is not set to 0 on handle */
1156
	(ss->ss_state == nua_callstate_ready && ds->ds_soa &&
1157
	 !NH_PISSET(nh, auto_ack))) {
1158
      nua_client_request_t *cru;
1159

1160 1161 1162 1163 1164 1165 1166 1167
      for (cru = ds->ds_cr; cru; cru = cru->cr_next) {
	if (cr != cru && cru->cr_offer_sent && !cru->cr_answer_recv)
	  break;
      }

      if (cru)
	/* A final response to UPDATE or PRACK with answer on its way? */;
      else if (nua_invite_client_ack(cr, NULL) > 0)
1168 1169 1170 1171 1172
	next_state = nua_callstate_ready;
      else
	next_state = nua_callstate_terminating;
    }
  }
1173

1174
  if (next_state == nua_callstate_terminating) {
1175 1176 1177 1178 1179
    /* Send BYE or CANCEL */
    /* XXX - Forking - send BYE to early dialog?? */
    if (ss->ss_state > nua_callstate_proceeding || status >= 200)
      error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL);
    else
1180
      error = nua_client_create(nh, nua_r_cancel,
1181 1182 1183
				&nua_cancel_client_methods, tags);

    if (error) {
1184 1185 1186
      next_state = nua_callstate_terminated;
      cr->cr_terminated = 1;
    }
1187
    cr->cr_graceful = 0;
1188
  }
1189 1190 1191 1192
  else if (next_state == nua_callstate_terminated) {
    cr->cr_graceful = 0;
    cr->cr_terminated = 1;
  }
1193

1194 1195
  ss->ss_reporting = 0;

1196
  signal_call_state(nh, ds, ss, status, phrase, next_state);
1197

1198 1199
  msg_destroy(response);

1200
  return 1;
1201 1202
}

1203 1204 1205 1206 1207
/**@fn void nua_ack(nua_handle_t *nh, tag_type_t tag, tag_value_t value, ...);
 *
 * Acknowledge a succesful response to INVITE request.
 *
 * Acknowledge a successful response (200..299) to INVITE request with the
1208
 * SIP ACK request message. This function is needed only if NUTAG_AUTOACK()
1209 1210 1211 1212 1213
 * parameter has been cleared.
 *
 * @param nh              Pointer to operation handle
 * @param tag, value, ... List of tagged parameters
 *
1214
 * @return
1215 1216 1217
 *    nothing
 *
 * @par Related Tags:
1218
 *    Header tags defined in <sofia-sip/sip_tag.h>
1219 1220 1221
 *
 * @par Events:
 *    #nua_i_media_error \n
1222
 *    #nua_i_state  (#nua_i_active, #nua_i_terminated)
1223 1224
 *
 * @sa NUTAG_AUTOACK(), @ref nua_call_model, #nua_i_state
1225 1226
 */

1227 1228
int nua_stack_ack(nua_t *nua, nua_handle_t *nh, nua_event_t e,
		  tagi_t const *tags)
1229
{
1230 1231
  nua_dialog_state_t *ds = nh->nh_ds;
  nua_dialog_usage_t *du = nua_dialog_usage_for_session(ds);
1232
  nua_session_usage_t *ss = nua_dialog_usage_private(du);
1233 1234
  nua_client_request_t *cr = du ? du->du_cr : NULL;
  int error;
1235

1236
  if (!cr || cr->cr_orq == NULL || cr->cr_status < 200) {
1237 1238 1239
    UA_EVENT2(nua_i_error, 900, "No response to ACK");
    return 1;
  }
1240

1241
  if (tags)
1242
    nua_stack_set_params(nua, nh, nua_i_error, tags);
1243

1244 1245
  nua_client_request_ref(cr);
  error = nua_invite_client_ack(cr, tags);
1246

1247
  if (error < 0) {
1248 1249
    if (ss->ss_reason == NULL)
      ss->ss_reason = "SIP;cause=500;text=\"Internal Error\"";
1250
    ss->ss_reporting = 1;	/* We report terminated state here if BYE fails */
1251 1252
    error = nua_client_create(nh, nua_r_bye, &nua_bye_client_methods, NULL);
    ss->ss_reporting = 0;
1253 1254 1255 1256
    signal_call_state(nh, ds, ss, 500, "Internal Error",
		      error
		      ? nua_callstate_terminated
		      : nua_callstate_terminating);
1257
  }
1258
  else if (ss)
1259
    signal_call_state(nh, ds, ss, 200, "ACK sent", nua_callstate_ready);
1260

1261
  nua_client_request_unref(cr);
1262

1263 1264
  return 0;
}
1265

1266 1267 1268 1269 1270 1271 1272 1273 1274 1275
/** Send ACK, destroy INVITE transaction.
 *
 *  @retval 1 if successful
 *  @retval < 0 if an error occurred
 */
static
int nua_invite_client_ack(nua_client_request_t *cr, tagi_t const *tags)
{
  nua_handle_t *nh = cr->cr_owner;
  nua_dialog_state_t *ds = nh->nh_ds;
1276
  nua_session_usage_t *ss = nua_dialog_usage_private(cr->cr_usage);
1277

1278 1279 1280 1281 1282 1283
  msg_t *msg;
  sip_t *sip;
  int error = -1;
  sip_authorization_t *wa;
  sip_proxy_authorization_t *pa;
  sip_cseq_t *cseq;
1284 1285
  int proxy_is_set;
  url_string_t *proxy;
1286 1287 1288